Three Ways to Make a POST Request from PHP
I’ve been doing a lot of work with services and working with them in various ways from PHP. There are a few different ways to do this, PHP has a curl extension which is useful, and if you can add PECL extensions then pecl_http is a better bet but there are a couple of different ways of using it. This post shows all these side-by-side.
POSTing from PHP Curl
This is pretty straightforward once you get your head around the way the PHP curl extension works, combining various flags with setopt() calls. In this example I’ve got a variable $xml which holds the XML I have prepared to send – I’m going to post the contents of that to flickr’s test method.
$url = 'http://api.flickr.com/services/xmlrpc/';
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $xml);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
curl_close($ch);
First we initialised the connection, then we set some options using setopt(). These tell PHP that we are making a post request, and that we are sending some data with it, supplying the data. The CURLOPT_RETURNTRANSFER flag tells curl to give us the output as the return value of curl_exec rather than outputting it. Then we make the call and close the connection – the result is in $response.
POSTing from Pecl_Http
Pecl_Http has two interfaces – one procedural and one object-oriented; we’ll start by looking at the former. This is even simpler than in curl, here’s the same script translated for pecl_http:
$url = 'http://api.flickr.com/services/xmlrpc/';
$response = http_post_data($url, $xml);
This extension has a method to expressly post a request, and it can optionally accept data to go with it, very simple and easy.
POSTing from Pecl_Http: the OO interface
Finally let’s see what the OO verison of the extension looks like. Exactly the same call as both the above examples, but using the alternative interface, means our code looks like this:
$url = 'http://api.flickr.com/services/xmlrpc/';
$request = new HTTPRequest($url, HTTP_METH_POST);
$request->setRawPostData($xml);
$request->send();
$response = $request->getResponseBody();
This example is quite a bit longer than the previous one, and you might think this indicates that this approach is more complicated. In some senses that is true and its probably overkill for our extremely trivial example. However it is worth mentioning that the pecl_http extension is extremely flexible and powerful, and can handle some cases that the curl extension can’t. So even if it looks more complicated here, it can still be an excellent choice to implement.
In Conclusion
That was a very fast round-up of three ways you could make an arbitrary web service call from PHP – hopefully these examples are clear and will help anyone just starting to implement something along these lines.
Nice post. :) There’s also using the streams HTTP context – see Example #1 here: http://php.net/manual/en/context.http.php – as well as opening a TCP stream and manually writing the HTTP request to it. PEAR::HTTP_Client and Zend_Http_Client from Zend Framework are other client library options as well.
Take a look at http://netevil.org/blog/2005/may/guru-multiplexing
Good article! I prefer curl personally. You made a typo in the curl code example. In the third line with curl_setopt you use the variable $curl which should be $ch like the others :)
Actually, there is a clean third way using built-in methods:
$params = array(‘http’=>array(‘method’=>’post’,’content’=>http_build_query($postArr)));
$context= stream_context_create($params);
$stream= fopen($url, ‘rb’, false, $context);
Here’s another variant on the same approach, setting a header for XML data and using
file_get_contents()
instead offopen()
(but the same fopen wrappers are used).[geshi lang=php]
$context = stream_context_create(array(
‘http’ => array(
‘method’ => ‘POST’,
‘header’ => ‘Content-Type: application/xml’,
‘content’ => $xml
)
));
$result = file_get_contents($url, false, $context);
[/geshi]
Thanks! This works excellent!
Very Useful.. :)
I had trouble at first with your example code on PHP 7 — I was receiving an empty $_POST array. Sending lower case ‘post’ was recognized using the file_get_contents(‘php://input’) method, but was *not* recognized via the $_POST function. Sending upper case ‘POST’ was recognized by both methods.
Right, PHP supports http natively as well, and is very easy to implement.
cURL and pecl’s http however help to process complex requests. Additionnaly cURL supports all kind of protocols, including sftp/ssh2/ftps :)
There’s also a few PEAR packages that you can use: HTTP_Request and HTTP_Client.
I also prefer the stream_context_create method it is simple, native and will do for most POST requests.
The title of this post should read: _Three Ways to Make a POST Request from PHP_ *(using extensions instead of built-in coolness)*
BTW php supports all kinds of protocols [1] too. Streams [2] FTW!
[1] http://php.net/wrappers
[2] http://php.net/streams
Not sure if this adds anything over the other commenters posts, but I’m posting it anyway :-)
http://netevil.org/blog/2006/nov/http-post-from-php-without-curl
Goodness, what a lot of comments! Thanks everyone for taking the time to comment, what excellent and useful contributions!! I definitely learned a few tricks from my readers today :)
One other advantage of cURL and pecl_http (which is built on libcurl, the same library as the cURL extension uses) is that they support parallel requests, which can be a significant performance boost if you need to execute multiple requests from a single process. Look at the curl_multi_* functions in cURL and HttpRequestPool in pecl_http.
yeh, as noticed by first comment you forget to see in PEAR. It is pretty simple to use php based library because it will be supported even curl or pecl libraries are unavailable.
you still have a typo in your example:
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
should be
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
..at least i assume it should :-)
Indeed, it should. I didn’t notice at first either, which resulted in the whole output being printed to STDOUT.
Hi, thanks for this cURL method, but how do I send post variables? To a page that only accepts post vars and return some result? Thanks.
If you just want to send variables rather than an XML string with your POST request, you can use http_build_query:
curl_setopt($ch, CURLOPT_POSTFIELDS,http_build_query($data));
(there’s an example at http://lornajane.net/posts/2009/putting-data-fields-with-php-curl)
Pingback: Bit.ly API: Bundles and Short URLs | LornaJane
ohhhhhhhhhhhhhhhhhh
Pingback: PHP Generating Post Data - PHP Solutions - Developers Q & A
What if I don’t want to send data or variables. What if I just want to post a link that I’ve been given that is already configured? ex: http://www.site.com/ap.aspx?foo=bar&...
Probably you don’t want to POST it if everything you need is already in the URL. Try:
file_get_contents(“http://www.site.com/ap.aspx?foo=bar”…”);
I have a requirement, calling nearly 50+ URLs to fetch the data. I tried in many ways. Finally Stick with HTTPRequestPool. Because it was faster than any other methods. I tried below methods.
1.file_get_contents($url) – took about 2 mins to complete all 50 requests
2.curl – took about 45 to 50 seconds to complete all 50 requests
3.HTTPRequest – took about 20 to 30 seconds to complete all 50 requests
4.HttpRequestPool – took about 10 to 15 seconds to complete all 50 requests
But still 10 to 15 seconds is also slow, when compare to my competitors. I want to complete all the 50 requests in a max of 3 to 6 seconds. How can I achieve my target time frame. Is there any alternatives apart from the above in PHP. If yes can anybody please tell me those.
Please help me to resolve this issue.
Thanks,
Sudhakar
I usually use http guzzle library to make a post request from php
So do I, for about the last 5 years! I really should write a blog post about that approach too, this is one of the most-read posts on my blog!
Finally , I did write the followup post! http://www.lornajane.net/posts/2018/make-a-post-request-from-php-with-guzzle