POSTing JSON Data With PHP cURL
I got this question the other day: how to send a POST request from PHP with correctly-formatted JSON data? I referred to the slides from my web services tutorial for the answer, and I thought I'd also put it here, with a bit of explanation. After all, publishing your slides is all very well, but if you didn't see the actual tutorial, I often think they aren't too useful.
We can't send post fields, because we want to send JSON, not pretend to be a form (the merits of an API which accepts POST requests with data in form-format is an interesting debate). Instead, we create the correct JSON data, set that as the body of the POST request, and also set the headers correctly so that the server that receives this request will understand what we sent:
$data = array("name" => "Hagrid", "age" => "36"); $data_string = json_encode($data); $ch = curl_init('http://api.local/rest/users'); curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST"); curl_setopt($ch, CURLOPT_POSTFIELDS, $data_string); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_HTTPHEADER, array( 'Content-Type: application/json', 'Content-Length: ' . strlen($data_string)) ); $result = curl_exec($ch);
All these settings are pretty well explained on the curl_setopt() page, but basically the idea is to set the request to be a POST request, set the json-encoded data to be the body, and then set the correct headers to describe that post body. The CURLOPT_RETURNTRANSFER is purely so that the response from the remote server gets placed in $result rather than echoed. If you're sending JSON data with PHP, I hope this might help!

Hello Lorna,
I just had the same challenge the other day and got to the same conclusion as your snippet.
Was fairly well documented on the PHP manual as you also pointed out.
Thanks for sharing this little gem of knowledge.
Cheers,
Peter
Thanks, I tried doing something similar style, but didn't set the header to application/json . I don't remember if it worked or not (it was a quick four liner suggestion to a colleague). But what happens if you forget setting the application/json header ?
If you don't set the header correctly, the service you are posting to may not understand what it is that you sent - the exact outcome depends entirely on the service though
Thanks Lorna.
Looking at replies below (and I don't know much about script hijacking), I think I will stick setting application/json in the http-header. And if I am writing a server I will (try) not accept simple plain/text.
Ohh BTW, I learned a lot from the slides that you linked in this post. I asked my colleague to read slide 39 - 42 for a quick introduction to SOAP. Pretty interesting stuff !
One thing to note is that some servers will recognize: application/javascript as application/json as well.
many frameworks expect the application/json content type to battle JSON Hijacking.
Well JSON hijacking would be relevant when sending JSON back in the response body, it has no relevance in the request body.
of course - but a server backend could demand that the request contains the Content-type header. JSON Hijacking uses a script tag, which in turn does not allow to set HTTP headers, unlike XmlHttpRequest.
Same thing without curl as a dependency (for the newbies who don't know about the excellent PHP's streams API):
$data = array('name' => 'Hagrid', 'age' => '36');
$data_string = json_encode($data);
$result = file_get_contents('http://api.local/rest/users', null, stream_context_create(array(
'http' => array(
'method' => 'POST',
'header' => 'Content-Type: application/json' . "\r\n"
. 'Content-Length: ' . strlen($data_string) . "\r\n",
'content' => $data_string,
),
)));
Thanks for adding the streams example, that's nice! Streams are pretty awesome but as you say, they're not as widely used or understood as they should be
+1 zaadjis, I was just thinking about the same.
Pingback: Lorna Mitchell Blog: Buchung JSON-Daten mit PHP cURL | PHP Boutique
Actually, you can trim down the request a bit and keep it simple.
You don't have to specify the content-length. It will be calculated automatically and appended to the headers.
Also, you don't have to declare the request as a post request explicitly. If you are setting the POSTFIELDS option for curl, curl will convert the request type to POST.
Pingback: Lorna Mitchell’s Blog: POSTing JSON Data With PHP cURL | Scripting4You Blog
Hey Lorna,
Could you give any examples of any of the discussions you elude to on the topic of accepting POST requests with data in form-format?
Cheers
/Matt
Matt, I will put it on my list of "things to blog about some rainy day" :)
Pingback: POSTing JSON Data With PHP cURL | PHP | Syngu
Pingback: Post JSON, XML data With cURL and receive it on other end « TechnoReaders.com
Thank you very much for this post, I've been struggling as a non-programmer to attempt to submit some basic form data to an API and this helped immensely.
For those who are having trouble accessing the data that gets posted use the following:
$body = @file_get_contents('php://input')