Reputation: 35703
I try to post data from angular 2 to php:
let headers = new Headers();
headers.append('Content-Type', 'application/json');
var order = {'order': this.orders};
this.http.post('http://myserver/processorder.php', JSON.stringify(order), {
headers: headers
}).subscribe(res => {
console.log('post result %o', res);
});
In angular 2 one can only post string as data and not Json? That's ok for me but I struggle to get the posted data on php. I tried $obj = $_POST['order'];
Upvotes: 10
Views: 12545
Reputation: 338
Hey if you are still reading this in 2023... I followed @Gabriel Martins answer above and that got me most of the way there... but adding 'data=' into the call was unncessary due to me choosing to use "php://input".
This project is currently in development and using Apache, php (8.1), Angular 16.
So my front end call (Using Angular 16) looks like the following:
public createPost(form: any){
let headers = new HttpHeaders();
headers.append('Accept', 'application/x-www-form-urlencoded');
headers.append('Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8')
//method value below is 'createPost'
let obj = JSON.stringify(Object.assign(form, {method: environment.endpoints.createPost.method}));
return this.http.post(environment.origin + environment.endpoints.createPost.url, obj, {['headers']: headers}).pipe()
//At this point, everything is almost the same as Gabriel's answer.
}
And my backend code (using PDO for mysql) and a small custom library is:
<?php
namespace System;
class Request {
private $headers = [];
private $method = [];
private $inputs = [];
private $files = [];
public static $instance;
public function __construct() {
self::$instance = $this;
$this->headers = apache_request_headers();
$this->method = strtolower($_SERVER['REQUEST_METHOD']);
if($this->method == 'post'){
//This is one spot where our answers are different.
//The addition of 'data=' causes unneeded parsing here.
//Just passing a stringified JSON seemed to work better.
//Note the second argument for true to json_decode.
$input = json_decode(file_get_contents("php://input"), true);
if(isset($this->headers['Content-Type'])){
$content_type = $this->headers['Content-Type'];
if($content_type == 'application/x-www-form-urlencoded' || strstr($content_type, 'text/plain')){
foreach($input as $key=>$value){
$this->inputs[$key] = filter_var($value, FILTER_DEFAULT);
}
}
}
}
}
/**
* returns this class instance
* @return self
*/
public static function get(){
if(self::$instance === null){
self::$instance = new self();
}
return self::$instance;
}
/**
* returns the method used to access the current request
* @return string
*/
public function get_method() : string{
return $this->method;
}
/**
* returns all the headers in the current request
* @return array
*/
public function get_headers() : array{
return $this->headers;
}
/**
* returns the header or null by key
* @param string $key
* @return type
*/
public function get_header(string $key){
return $this->headers[$key] ?? null;
}
/**
* returns the input value in the request or null
* @param string $var
* @return type
*/
public function get_input(string $var){
return $this->inputs[$var] ?? null;
}
/**
* returns all the input fields in the current request
* @return array
*/
public function get_all_inputs(): array{
return $this->inputs;
}
public function get_files(): array{
return $this->files;
}
}
?>
The public API code that actually calls my PDO library is:
<?php
require_once(__DIR__."/../Models/BlogPosts.php");
require_once(__DIR__."/../System/Request.php");
$blogModel = new \Models\BlogPost();
$req = \System\Request::get();
switch($req->get_input('method')){
case 'createPost':
print_r($blogModel->createPost(
$req->get_input('url'),
$req->get_input('title'),
$req->get_input('description'),
$req->get_input('author'),
$req->get_input('category'),
$req->get_input('sequence'),
$req->get_input('image'),
$req->get_input('imageWebp'),
$req->get_input('content')
));
break;
case 'getFullPostByID':
print_r($blogModel->getFullPostByID($req->get_input('id')));
break;
case 'getAllPosts':
print_r($blogModel->getAllBasicPostInfo());
break;
}
?>
Anyway, I hope that helps someone.. I also made sure to append a slash at the end of the request URL, to send the request to 'api/posts.php/' instead of 'api/posts.php'
Upvotes: 0
Reputation: 662
I do not know if it's bad practice but it seems right to me, although it bothers me a little
const headers = new Headers();
headers.append('Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8');
const obj = { nome: 'gabriel', age: 20 };
const body = 'data=' + JSON.stringify(obj);
this.http.post('/test.php', body, { headers })
.subscribe(res => console.log(res.json()), res => console.error(res))
And in php
$post = json_decode($_POST['data']);
Upvotes: 5
Reputation: 202176
Agreed with you that we can't at the moment provide object instead of string. It's a feature in progress. See this issue:
Regarding your problem to get JSON data on the server side, this question should help you:
Upvotes: 2
Reputation: 1946
Marc B is correct, however what is happening is that the $_POST array will contain an empty value with a key set to the JSON string you are passing...
Array
(
[{"order":"foobar"}] =>
)
You "can" grab that (although this would be the wrong approach) by getting the key using...
key($_POST)
for example:
$obj = json_decode(key($_POST));
echo $obj->order;
BUT what you can do is send the data as value key pairs:
let headers = new Headers();
headers.append('Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8');
let order = 'order=foobar';
this.http.post('http://myserver/processorder.php', order, {
headers: headers
}).subscribe(res => {
console.log('post result %o', res);
});
Then in PHP you can grab the data using:
$_POST['order']
Few things to note:
Upvotes: 9