Solved

php creating an api post problem

Posted on 2016-08-23
9
47 Views
Last Modified: 2016-08-26
Hi
it is the first time i learn how to write an api. i have the folder structure of: apihub/v1/api.php

the GET part works: i get all the customers and a customer according to an id. i have issue with POST variables.

i read that instead of reading POST array one should use : file_get_contents("php://input")

so i have this code:
    $customer = json_decode(file_get_contents("php://input"));

    var_dump($this->get_request_method());
    var_dump($customer);

Open in new window


and when i use the chrome extension i get NULL, but if i don't use the json_decode i so get the json string. what am i missing here? and how can i use that, cause according to it i want to write the query to the database.
post data stringgetting null with the decode
best regards
0
Comment
Question by:derrida
  • 3
  • 3
  • 2
  • +1
9 Comments
 
LVL 34

Assisted Solution

by:gr8gonzo
gr8gonzo earned 250 total points
ID: 41767178
So the content type of the request is going to determine whether or not you get a $_POST array. When you're POSTing a web form, browsers usually submit a content type of "application/x-www-form-urlencoded" which tells PHP, "Hey, the content inside the POST data is simply a list of fields and their values from a web form." PHP then knows to transform that content ("foo=1&bar=abc") into $_POST ($_POST["foo"] = 1, $_POST["bar"] = "abc").

If you're dealing with situations where the content type isn't passed or the content type value does not specify form encoding, then PHP will not auto-populate the $_POST variable.

In those scenarios, the only way to access the raw post data is from that special php://input stream.

If it's form-encoded data but is missing the right content type, you can use this common little one-liner
to re-create the $_POST array:
parse_str(file_get_contents("php://input"), $_POST);

To be honest, that seems to match the type of data you're showing in the screenshots. Your first screenshot doesn't show JSON data - it shows form-encoded data, so the above line would give you a $_POST array with your values.

Now, if the POSTed data really is something else, like JSON or XML (maybe you want to accept those types of content as alternatives), then you'd use the methods you've described in your post (file_get_contents() to retrieve the raw string, then json_decode to convert the string into an object).

If it's really JSON and you're getting a null in response, then that means PHP couldn't decode the JSON for some reason. Maybe it's malformed or something. PHP is extremely finicky when it comes to decoding JSON - it'll either work perfectly or not at all. So if you get a null, then the best thing to do is to make sure you separate out the file_get_contents and json_decode lines, trim and then dump out the string so you can paste it into a JSON checker:

$raw_post_data = file_get_contents("php://input");    // Get the raw POST data
$raw_post_data = trim($raw_post_data);                      // Get rid of any surrounding whitespace
file_put_contents("last_request.json",$raw_post_data); // Write a new file containing the POST data
$decoded_object = json_decode($raw_post_data);
var_dump($decoded_object);
0
 
LVL 13

Expert Comment

by:Abhijeet Rananaware
ID: 41767224
Try to verify data your are posting is in a correct format. I was getting the same error when the issue was with the  JSON format.

http://json.parser.online.fr/
1
 
LVL 108

Expert Comment

by:Ray Paseur
ID: 41767495
Have you tried var_dump($_POST)?  Or maybe var-dump($_REQUEST)?  The latter should also include the $_GET and $_COOKIE information.
0
 
LVL 1

Author Comment

by:derrida
ID: 41768212
hi
gr8gonzo good explanation, yet with your separation, i still get NULL. and with the chrome browser extention i do use: application/x-www-form-urlencoded

ray: i attach the image of bar_dump post. the values are there. so somehow the json_decode return NULL and i don't understand why.
should i just use regular post array, in order to query the database? therefore skeep the decode or totally the file_get_contents? again, the question is why i get the NULL.

post values
0
Do You Know the 4 Main Threat Actor Types?

Do you know the main threat actor types? Most attackers fall into one of four categories, each with their own favored tactics, techniques, and procedures.

 
LVL 108

Expert Comment

by:Ray Paseur
ID: 41768865
json_decode return NULL and i don't understand why.
PHP has ways of discerning the errors in JSON strings.

It would be easier for us to help you if you would post the test data and code snippets instead of pictures  of test data and code!  We could use copy / paste to ensure we were working with the same test data set you're using.  Please have a look at var_export().

Here is my teaching example showing how to decode json strings and detect errors, if any.
<?php // demo/json_decode_show_errors.php
/**
 * JSON stands for JavaScript Object Notation
 * http://json.org/
 *
 * JSON support in PHP does not have very good error handling
 *
 * JSON strings are all UTF-8
 * http://www.experts-exchange.com/articles/11880/Unicode-PHP-and-Character-Collisions.html
 *
 * PHP man page references
 * http://php.net/manual/en/json.constants.php
 * http://php.net/manual/en/function.json-decode.php
 * http://php.net/manual/en/function.json-encode.php
 * http://php.net/manual/en/function.json-last-error.php
 * http://php.net/manual/en/function.json-last-error-msg.php
 */
error_reporting(E_ALL);
echo '<pre>';

// SEE TEST DATA AT http://www.experts-exchange.com/Programming/Languages/Scripting/JavaScript/Q_28523915.html#a40339939
$jso = <<<EOD
{"id":"tag:search.twitter.com,2005:389903668427763712","objectType":"activity","actor":{"objectType":"person","id":"id:twitter.com:91239297","link":"http://www.twitter.com/OGkush103","displayName":"WalkingLick74","postedTime":"2009-11-20T01:21:39.000Z","image":"https://si0.twimg.com/profile_images/378800000593715086/755411d8bdc495472c2d7ed50e319582_normal.jpeg","summary":"Self-Made, Self Paid..... I always had the mind to get it like a man, head first bout my younging Ean! #YOLO","links":[{"href":null,"rel":"me"}],"friendsCount":468,"followersCount":677,"listedCount":0,"statusesCount":25504,"twitterTimeZone":"Alaska","verified":false,"utcOffset":"-28800","preferredUsername":"OGkush103","languages":["en"],"location":{"objectType":"place","displayName":"Boston George Crib"},"favoritesCount":26},"verb":"post","postedTime":"2013-10-15T00:00:53.000Z","generator":{"displayName":"Twitter for iPhone","link":"http://twitter.com/download/iphone"},"provider":{"objectType":"service","displayName":"Twitter","link":"http://www.twitter.com"},"link":"http://twitter.com/OGkush103/statuses/389903668427763712","body":"You a killer you on twitter, You'n do NO talking","object":{"objectType":"note","id":"object:search.twitter.com,2005:389903668427763712","summary":"You a killer you on twitter, You'n do NO talking","link":"http://twitter.com/OGkush103/statuses/389903668427763712","postedTime":"2013-10-15T00:00:53.000Z"},"favoritesCount":0,"location":{"objectType":"place","displayName":"Mississippi, US","name":"Mississippi","country_code":"United States","twitter_country_code":"US","link":"https://api.twitter.com/1.1/geo/id/43d2418301bf1a49.json","geo":{"type":"Polygon","coordinates":[[[-91.65500899999999,30.146096],[-91.65500899999999,34.996099],[-88.097888,34.996099],[-88.097888,30.146096]]]}},"geo":{"type":"Point","coordinates":[31.99686058,-88.72688823]},"twitter_entities":{"hashtags":[],"symbols":[],"urls":[],"user_mentions":[]},"twitter_filter_level":"medium","twitter_lang":"en","retweetCount":0,"gnip":{"matching_rules":[{"tag":null}],"language":{"value":"en"}}}
EOD;

// IF DECODING SUCCEEDS
$obj = json_decode($jso);
if ($obj)
{
    // SHOW SOME PARTS OF THE OBJECT
    $x = $obj->objectType;
    $y = $obj->actor->displayName;
    echo PHP_EOL . "$x $y" . PHP_EOL;

    // ACTIVATE THIS TO SHOW THE ENTIRE OBJECT
    // var_dump($obj);
}

// IF DECODING FAILS?
if (!$obj) echo json_last_error_message();

function json_last_error_message()
{
    static $errors = array
    ( JSON_ERROR_NONE           => null
    , JSON_ERROR_DEPTH          => 'Maximum stack depth exceeded'
    , JSON_ERROR_STATE_MISMATCH => 'Underflow or the modes mismatch'
    , JSON_ERROR_CTRL_CHAR      => 'Unexpected control character found'
    , JSON_ERROR_SYNTAX         => 'Syntax error, malformed JSON'
    , JSON_ERROR_UTF8           => 'Malformed UTF-8 characters, possibly incorrectly encoded'
    )
    ;
    // ADD THESE AT PHP 5.5+ OR USE json_last_error_msg()
    if (defined('JSON_ERROR_RECURSION'))        $errors[JSON_ERROR_RECURSION]        = 'One or more recursive references in the value to be encoded';
    if (defined('JSON_ERROR_INF_OR_NAN'))       $errors[JSON_ERROR_INF_OR_NAN]       = 'One or more NAN or INF values in the value to be encoded';
    if (defined('JSON_ERROR_UNSUPPORTED_TYPE')) $errors[JSON_ERROR_UNSUPPORTED_TYPE] = 'A value of a type that cannot be encoded was given';

    $error = json_last_error();

    return array_key_exists($error, $errors)
    ? $errors[$error]
    : "Unknown error ({$error})"
    ;
}

Open in new window

0
 
LVL 108

Accepted Solution

by:
Ray Paseur earned 250 total points
ID: 41768998
See if this helps make sense of things.  If your PHP script is expecting a POST request, you should use the $_POST array to find the request variables.  You can copy this script and install it on your server to see how it works.
https://iconoun.com/demo/temp_derrida.php
<?php // demo/temp_derrida.php
/**
 * https://www.experts-exchange.com/questions/28965062/php-creating-an-api-post-problem.html
 *
 * JSON stands for JavaScript Object Notation
 * http://json.org/
 *
 * JSON support in PHP does not have very good error handling
 *
 * JSON strings are all UTF-8
 * http://www.experts-exchange.com/articles/11880/Unicode-PHP-and-Character-Collisions.html
 *
 * PHP man page references
 * http://php.net/manual/en/json.constants.php
 * http://php.net/manual/en/function.json-decode.php
 * http://php.net/manual/en/function.json-encode.php
 * http://php.net/manual/en/function.json-last-error.php
 * http://php.net/manual/en/function.json-last-error-msg.php
 */
error_reporting(E_ALL);


// IF THERE IS A POST-METHOD REQUEST
if (!empty($_POST))
{
    // MAKE A JSON STRING FROM THE POST REQUEST DATA, DISPLAY THE JSON STRING
    $jso = json_encode($_POST);
    echo '<pre>';
    echo $jso;
    echo PHP_EOL;

    // DECODE THE JSON STRING
    $obj = json_decode($jso);

    // IF DECODING FAILS?
	if (!$obj) echo json_last_error_message();

	// SHOW THE OBJECT
    var_dump($obj);

    // SHOW HOW TO USE THE OBJECT
    echo PHP_EOL . "THE HIDDEN VALUE IN 'obj->secret' IS <b>$obj->secret</b>";

    echo '<pre>';
}


// CREATE A FORM TO MAKE A POST-METHOD REQUEST
$form = <<<EOD
<form method="post">
<input type="hidden" name="secret" value="foo" />
<input type="text"   name="public" placeholder="Your name" />
<input type="submit" value="Go!" />
</form>
EOD;

echo $form;


// AN ERROR DISPLAY THAT WILL WORK WITH PHP 5.3.3+
function json_last_error_message()
{
    static $errors = array
    ( JSON_ERROR_NONE           => null
    , JSON_ERROR_DEPTH          => 'Maximum stack depth exceeded'
    , JSON_ERROR_STATE_MISMATCH => 'Underflow or the modes mismatch'
    , JSON_ERROR_CTRL_CHAR      => 'Unexpected control character found'
    , JSON_ERROR_SYNTAX         => 'Syntax error, malformed JSON'
    , JSON_ERROR_UTF8           => 'Malformed UTF-8 characters, possibly incorrectly encoded'
    )
    ;
    // ADD THESE AT PHP 5.5+ OR USE json_last_error_msg()
    if (defined('JSON_ERROR_RECURSION'))        $errors[JSON_ERROR_RECURSION]        = 'One or more recursive references in the value to be encoded';
    if (defined('JSON_ERROR_INF_OR_NAN'))       $errors[JSON_ERROR_INF_OR_NAN]       = 'One or more NAN or INF values in the value to be encoded';
    if (defined('JSON_ERROR_UNSUPPORTED_TYPE')) $errors[JSON_ERROR_UNSUPPORTED_TYPE] = 'A value of a type that cannot be encoded was given';

    $error = json_last_error();

    return array_key_exists($error, $errors)
    ? $errors[$error]
    : "Unknown error ({$error})"
    ;
}

Open in new window

On submit, outputs something like:
{"secret":"foo","public":"Ray"}
object(stdClass)#1 (2) {
  ["secret"]=>
  string(3) "foo"
  ["public"]=>
  string(3) "Ray"
}

THE HIDDEN VALUE IN 'obj->secret' IS foo

Open in new window

0
 
LVL 34

Expert Comment

by:gr8gonzo
ID: 41769064
Did you try the parse_str line I mentioned? Again, your screenshots show that you are posting form content, not JSON, so try:

$raw = file_get_contents("php://input");
parse_str($raw, $_POST);
var_dump($raw);
var_dump($_POST);
0
 
LVL 1

Author Closing Comment

by:derrida
ID: 41771591
good explanation and code example
0
 
LVL 34

Expert Comment

by:gr8gonzo
ID: 41771861
So the issue is resolved? What was the fix?
0

Featured Post

Easy Project Management (No User Manual Required)

Manage projects of all sizes how you want. Great for personal to-do lists, project milestones, team priorities and launch plans.
- Combine task lists, docs, spreadsheets, and chat in one
- View and edit from mobile/offline
- Cut down on emails

Join & Write a Comment

Popularity Can Be Measured Sometimes we deal with questions of popularity, and we need a way to collect opinions from our clients.  This article shows a simple teaching example of how we might elect a favorite color by letting our clients vote for …
Nothing in an HTTP request can be trusted, including HTTP headers and form data.  A form token is a tool that can be used to guard against request forgeries (CSRF).  This article shows an improved approach to form tokens, making it more difficult to…
Learn how to match and substitute tagged data using PHP regular expressions. Demonstrated on Windows 7, but also applies to other operating systems. Demonstrated technique applies to PHP (all versions) and Firefox, but very similar techniques will w…
Explain concepts important to validation of email addresses with regular expressions. Applies to most languages/tools that uses regular expressions. Consider email address RFCs: Look at HTML5 form input element (with type=email) regex pattern: T…

760 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

19 Experts available now in Live!

Get 1:1 Help Now