Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

file_get_contents('php://input'); with application/x-www-form-urlencoded;

I've read a few questions about the subject here on but couldn't find the answer I'm looking for. I'm doing some $.post with jQuery to a PHP5.6 server.

$.post('/', {a:100, b:'test'}, function(data){
}, 'json');

The encoding from the console is

Content-Type    application/x-www-form-urlencoded; charset=UTF-8

If I try to read the POST data with a regular $_POST, PHP5.6 alerts me

PHP Deprecated:  Automatically populating $HTTP_RAW_POST_DATA is deprecated and will be removed in a future version. To avoid this warning set 'always_populate_raw_post_data' to '-1' in php.ini and use the php://input stream instead

So then I've tried the suggestion, added always_populate_raw_post_data = -1 in php.ini and

json_decode(file_get_contents("php://input"));

PHP5.6 alerts me that it is invalid

PHP Warning:  First parameter must either be an object or the name of an existing class

So I've dumped file_get_contents("php://input") and it's a string.

a=100&b="test"

So I've parsed the string and encoded then decoded

parse_str(file_get_contents("php://input"), $data);             
$data = json_decode(json_encode($data));
var_dump($data);    

And THEN I finally have my $data as an object and not an array, as a true JSON object.

I've resorted to keep on using $_POST for now... But then I'm wondering about upgrading PHP..

The question here is that, is there a straighter forward solution to this or does it mean using file_get_contents("php://input") also means doing the parsing decoding encoding shenanigans?

Edit: so it appears this doesn't work either on multi levels json's. Consider the following:

{"a":100, "b":{"c":"test"}}

As sent in Ajax/Post

{a:100, b:{c:"test"}}

Doing

parse_str(file_get_contents("php://input"), $post);
var_dump($post);

Will output

array(2) {
 ["a"]=>string(8) "100"
 ["b"]=>string(16) "{"c":"test"}"
}

Or doing (as suggested)

parse_str(file_get_contents("php://input"), $post);
$post= (object)$post;

Will output

object(stdClass)#11 (2) {
 ["a"]=>string(8) "100"
 ["b"]=>string(16) "{"c":"test"}"

}

How do I transform file_get_contents("php://input") into a true object with the same "architecture" without using a recursive function?

Edit2 : My mistake, the suggested worked, I got side tracked in the comments with JSON.stringify which caused the error. Bottom line: it works with either json_decode(json_encode($post)) or $post=(object)$post;

To recap, using jQuery $.post :

$.post('/', {a:100, b:{c:'test'}}, function(data){
}, 'json');

parse_str(file_get_contents("php://input"), $data);             
$data = json_decode(json_encode($data));

or

parse_str(file_get_contents("php://input"), $data);
$data= (object)$data;

No need to use JSON.stringify

like image 569
Eric Avatar asked Sep 19 '14 15:09

Eric


3 Answers

In order to send raw json data, you have to stop jQuery from url-encoding it:

    data = {"a":"test", "b":{"c":123}};

    $.ajax({
        type: 'POST',
        url:  '...',
        data: JSON.stringify(data), // I encode it myself
        processData: false          // please, jQuery, don't bother
    });

On the php side, just read php://input and json_decode it:

$req = file_get_contents("php://input");
$req = json_decode($req);
like image 134
georg Avatar answered Oct 11 '22 15:10

georg


Receiving serialized/urlencoded POST data in the request's POST body as you are, you've correctly transformed it into an array with parse_str() already.

However, the step of encoding then decoding JSON in order to transform that into the object (as opposed to array) you're looking for is unnecessary. Instead, PHP will happily cast an associative array into an object of class stdClass:

parse_str(file_get_contents("php://input"), $data);
// Cast it to an object
$data = (object)$data;

var_dump($data);

A little more information is available in the PHP documentation on type casting.

like image 20
Michael Berkowski Avatar answered Oct 11 '22 16:10

Michael Berkowski


My mistake, the suggested worked, I got side tracked in the comments with JSON.stringify which caused the error. Bottom line: it works with either json_decode(json_encode($post)) or $post=(object)$post; The answer Michael gave is correct but side tracked me and I left the error in my code. JSON.stringify is only useful when posting the data from a form as I replied in the comment.

like image 25
Eric Avatar answered Oct 11 '22 17:10

Eric