我正在尝试将Angular 6 CRUD放在一起。我的addCoins方法似乎将记录添加了两次。
addCoin(name, price) {
const obj = {
name: name,
price: price
};
const uri = 'http://localhost/ng6crud/api/post-coins/' + name + '/' + price;
this
.http
.post(uri, obj)
.subscribe(res =>
console.log('Done'));
}
我创建了一个简单的PHP api,位于ng6crud目录中。以下是api / post-coins /的代码-如果我使用postman张贴到API,那么它只会插入一次数据。
<?php
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: POST, GET, PUT, DELETE, OPTIONS');
header('Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept');
$path = ltrim($_SERVER['REQUEST_URI'], '/'); // Trim leading slash(es)
$elements = explode('/', $path); // Split path on slashes
global $name, $price;
if(!empty($elements[3]))
{
$name = $elements[3];
}
if(!empty($elements[4]))
{
$price = $elements[4];
}
global $server;
$server = "localhost";
global $user;
$user = "someU";
global $pwd;
// $pwd = "someP"; // production
$pwd = "someP"; // local
global $db;
$db = "someDb";
//open connection to mysql db
$connection = mysqli_connect($server,$user,$pwd,$db) or die("Error " . mysqli_error($connection));
//fetch table rows from mysql db
$sql = "INSERT into coins (name, price) VALUES('" . $name . "','" . $price . "')";
// echo $sql;
// die();
if ($connection->query($sql) === TRUE) {
// echo "Record updated successfully";
} else {
// echo "Error updating record: " . $connection->error;
}
$connection->close();
?>
.htaccess文件和httpd-vhosts.conf文件中的“”标记的组合允许api / post-coins /接受sql插入中包括的“ name”和“ price”两个参数语句-例如api / post-coins / rupple / 1.00会在数据库中插入一行。
以下是.htaccess文件:
IndexIgnore * # prevent directory listing
Order deny,allow
Allow from *
# ------------------------------------------
# Rewrite so that php extentions are not shown
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^.*$ index.php%{REQUEST_URI} [QSA,L]
以下是httpd-vhosts.conf文件中“”标记内的Location标记:
<Location /post-coins>
ForceType appllication/x-http-php
</Location>
再一次,如果我使用邮差发布到api / post-coins / rupple / 1.00,则数据库中将只有一个条目。在Angular 6中使用该服务时,它将两次插入数据。我尝试删除.subscribe,但是没有插入任何内容,并且尝试删除URL末尾的两个参数,但是结果是两个空条目。
预先感谢
要回答@Vikas有关如何实现的问题,以下是create.component.html:
<div class="panel panel-primary">
<div class="panel-heading">
{{ title }}
</div>
<div class="panel-body">
<form [formGroup]="angForm" novalidate>
<div class="form-group">
<label class="col-md-4">Coin Name</label>
<input type="text" class="form-control" formControlName="name" #name />
</div>
<div *ngIf="angForm.controls['name'].invalid && (angForm.controls['name'].dirty || angForm.controls['name'].touched)" class="alert alert-danger">
<div *ngIf="angForm.controls['name'].errors.required">
Name is required.
</div>
</div>
<div class="form-group">
<label class="col-md-4">Coin Price</label>
<input type="text" class="form-control" formControlName="price" #price/>
</div>
<div *ngIf="angForm.controls['price'].invalid && (angForm.controls['price'].dirty || angForm.controls['price'].touched)" class="alert alert-danger">
<div *ngIf="angForm.controls['price'].errors.required">
Price is required.
</div>
</div>
<div class="form-group">
<button (click)="addCoin(name.value, price.value)" [disabled]="angForm.pristine || angForm.invalid" class="btn btn-primary">Add</button>
</div>
</form>
</div>
</div>
creat.component.ts:
import { Component, OnInit } from '@angular/core';
import { CoinService } from '../../service/coin.service';
import { FormGroup, FormBuilder, Validators } from '@angular/forms';
@Component({
selector: 'app-create',
templateUrl: './create.component.html',
styleUrls: ['./create.component.css']
})
export class CreateComponent implements OnInit {
title = 'Add Coin';
angForm: FormGroup;
constructor(private coinservice: CoinService, private fb: FormBuilder) {
this.createForm();
}
createForm() {
this.angForm = this.fb.group({
name: ['', Validators.required ],
price: ['', Validators.required ]
});
}
addCoin(name, price) {
this.coinservice.addCoin(name, price);
}
ngOnInit() {
}
}
还有coin.service.ts
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
@Injectable()
export class CoinService {
result: any;
constructor(private http: HttpClient) {}
addCoin(name, price) {
const obj = {
name: name,
price: price
};
const uri = 'http://localhost/ng5crud/api/post-coins/' + name + '/' + price;
this
.http
.post(uri, obj)
.subscribe(res =>
console.log('Done'));
}
getCoins() {
const uri = 'http://localhost/ng5crud/api/get-coins/';
return this
.http
.get(uri);
}
editCoin(id) {
const uri = 'http://localhost/ng5crud/api/get-coins-id/' + id;
return this
.http
.get(uri);
}
updateCoin(name, price, id) {
const uri = 'http://localhost/ng5crud/api/put-coins/' + id;
const obj = {
name: name,
price: price
};
this
.http
.post(uri, obj)
.subscribe(res => console.log('Done'));
}
deleteCoin(id) {
const uri = 'http://localhost/ng5crud/api/delete-coins/' + id;
return this
.http
.get(uri);
}
}
和routerConfig.ts
import { Routes } from '@angular/router';
import { CreateComponent } from './components/create/create.component';
import { EditComponent } from './components/edit/edit.component';
import { IndexComponent } from './components/index/index.component';
import { DeleteComponent } from './components/delete/delete.component';
export const appRoutes: Routes = [
{ path: 'create',
component: CreateComponent
},
{
path: 'edit/:id',
component: EditComponent
},
{ path: 'index',
component: IndexComponent
},
{ path: 'delete/:id',
component: DeleteComponent
}
];
@Debojyoti,我刚刚看到了您的回复。我最终创建了以下内容,但没有返回任何内容,但是我在网络面板中进行了查看-请参见下面的屏幕截图:
import { HttpErrorResponse } from '@angular/common/http';
import { throwError } from 'rxjs';
import { catchError} from 'rxjs/operators';
addCoin(name, price) {
const obj = {
name: name,
price: price
};
const uri = 'http://localhost/ng5crud/api/post-coins/' + name + '/' + price;
this
.http
.post(uri, obj)
.pipe(
catchError(this.handleError) // then handle the error
)
.subscribe(res =>
console.log('Done'));
}
private handleError(error: HttpErrorResponse) {
if (error.error instanceof ErrorEvent) {
// A client-side or network error occurred. Handle it accordingly.
console.error('An error occurred:', error.error.message);
} else {
// The backend returned an unsuccessful response code.
// The response body may contain clues as to what went wrong,
console.error(
`Backend returned code ${error.status}, ` +
`body was: ${error.error}`);
}
// return an observable with a user-facing error message
return throwError(
'Something happened; please try again later.');
};
答案 0 :(得分:0)
看起来PHP应用程序和Angular应用程序在协议(http / https),域和端口的单独组合上运行。我看到CORS标头已添加到PHP代码中。
这使我相信正在发出2个请求,一个可以查看是否根据CORS(一个OPTIONS
)请求和正常的POST
请求而允许该请求。因此,该记录被插入两次。您可以检测到请求方法并返回CORS标头,并在CORS OPTIONS
请求上适当地将响应主体设置为空,并在POST
请求上进行插入,类似于以下内容(未经测试)。
<?php
if ($_SERVER['method'] === 'OPTIONS') {
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: POST, GET, PUT, DELETE, OPTIONS');
header('Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept');
header("HTTP/1.1 200 OK");
exit;
}
if ($_SERVER['method'] === 'POST') {
header("HTTP/1.1 200 OK");
$path = ltrim($_SERVER['REQUEST_URI'], '/'); // Trim leading slash(es)
$elements = explode('/', $path); // Split path on slashes
global $name, $price;
if (!empty($elements[3])) {
$name = $elements[3];
}
if (!empty($elements[4])) {
$price = $elements[4];
}
global $server;
$server = "localhost";
global $user;
$user = "someU";
global $pwd;
// $pwd = "someP"; // production
$pwd = "someP"; // local
global $db;
$db = "someDb";
//open connection to mysql db
$connection = mysqli_connect($server, $user, $pwd, $db) or die("Error " . mysqli_error($connection));
//fetch table rows from mysql db
$sql = "INSERT into coins (name, price) VALUES('" . $name . "','" . $price . "')";
// echo $sql;
// die();
if ($connection->query($sql) === true) {
// echo "Record updated successfully";
} else {
// echo "Error updating record: " . $connection->error;
}
$connection->close();
exit;
}
header("HTTP/1.1 404 Not Found");
exit;
?>
答案 1 :(得分:0)
让php不接受第一个飞行前请求(选项)
只需像修改您的php代码一样
<?php
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: POST, GET, PUT, DELETE, OPTIONS');
header('Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept');
if ($_SERVER['REQUEST_METHOD'] != "OPTIONS") {
$path = ltrim($_SERVER['REQUEST_URI'], '/'); // Trim leading slash(es)
$elements = explode('/', $path); // Split path on slashes
global $name, $price;
if (!empty($elements[3])) {
$name = $elements[3];
}
if (!empty($elements[4])) {
$price = $elements[4];
}
global $server;
$server = "localhost";
global $user;
$user = "someU";
global $pwd;
// $pwd = "someP"; // production
$pwd = "someP"; // local
global $db;
$db = "someDb";
//open connection to mysql db
$connection = mysqli_connect($server, $user, $pwd, $db) or die("Error " . mysqli_error($connection));
//fetch table rows from mysql db
$sql = "INSERT into coins (name, price) VALUES('" . $name . "','" . $price . "')";
// echo $sql;
// die();
if ($connection->query($sql) === TRUE) {
// echo "Record updated successfully";
} else {
// echo "Error updating record: " . $connection->error;
}
}
$connection->close();
?>
答案 2 :(得分:0)
我已经弄清楚了,感谢大家帮助我一遍又一遍。
由于我的PHP API是用于所有密集用途的“ GET”:
const uri = 'http://localhost/ng5crud/api/post-coins/' + name + '/' + price;
然后调用“ POST”功能将两次关闭API-请参见下面的屏幕截图:
const obj = {
name: name,
price: price
};
const uri = 'http://localhost/ng5crud/api/post-coins/' + name + '/' + price;
this
.http
.post(uri, obj)
因此,我将其更改为“ GET”功能,并且仅需一次输入即可完美运行
addCoin(name, price) {
const obj = {
name: name,
price: price
};
const uri = 'http://localhost/ng5crud/api/post-coins/' + name + '/' + price;
this
.http
.get(uri)
.pipe(
catchError(this.handleError), // then handle the error
map(res => {
console.log(res);
})
)
.subscribe(res =>
console.log('Done'));
}
在此过程中,我从(another stackoverflow post - see @nodirabegimxonoyim 's answer)发现,地图在Angular 6中的导入方式不同,并且在.get方法中的使用方式不同
而不是使用
导入 import 'rxjs/add/operator/map';
您使用以下内容:
import { map } from 'rxjs/operators';
代替.get()。map()
this
.http
.get(uri)
.map(res => {console.log(res)});
您在.pipe内使用地图
this
.http
.get(uri)
.pipe(
catchError(this.handleError), // then handle the error
map(res => {
console.log(res);
})
)
总的来说,以下是我新使用的coin.service.ts:
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { HttpErrorResponse } from '@angular/common/http';
import { throwError } from 'rxjs';
import { catchError } from 'rxjs/operators';
import { map } from 'rxjs/operators';
@Injectable()
export class CoinService {
constructor(private http: HttpClient) {}
addCoin(name, price) {
const obj = {
name: name,
price: price
};
const uri = 'http://localhost/ng5crud/api/post-coins/' + name + '/' + price;
this
.http
.get(uri)
.pipe(
catchError(this.handleError), // then handle the error
map(res => {
console.log(res);
})
)
.subscribe(res =>
console.log('Done'));
}
getCoins() {
const uri = 'http://localhost/ng5crud/api/get-coins/';
return this
.http
.get(uri)
.pipe(
catchError(this.handleError), // then handle the error
map(res => {
console.log(res);
})
);
}
editCoin(id) {
const uri = 'http://localhost/ng5crud/api/get-coins-id/' + id;
return this
.http
.get(uri)
.pipe(
catchError(this.handleError), // then handle the error
map(res => {
console.log(res);
})
);
}
updateCoin(name, price, id) {
const uri = 'http://localhost/ng5crud/api/put-coins/' + id;
const obj = {
name: name,
price: price
};
this
.http
.post(uri, id)
.pipe(
catchError(this.handleError), // then handle the error
map(res => {
console.log(res);
})
)
.subscribe(res => console.log('Done'));
}
deleteCoin(id) {
const uri = 'http://localhost/ng5crud/api/delete-coins/' + id;
return this
.http
.get(uri)
.pipe(
catchError(this.handleError), // then handle the error
map(res => {
console.log(res);
})
);
}
private handleError(error: HttpErrorResponse) {
if (error.error instanceof ErrorEvent) {
// A client-side or network error occurred. Handle it accordingly.
console.error('An error occurred:', error.error.message);
} else {
// The backend returned an unsuccessful response code.
// The response body may contain clues as to what went wrong,
console.error(
`Backend returned code ${error.status}, ` +
`body was: ${error.error}`);
}
// return an observable with a user-facing error message
return throwError(
'Something happened; please try again later.');
}
}
非常感谢您的帮助。这使我回到了90年代初,那时程序员很好,我们会互相帮助。