308

I'm using PHP's function file_get_contents() to fetch contents of a URL and then I process headers through the variable $http_response_header.

Now the problem is that some of the URLs need some data to be posted to the URL (for example, login pages).

How do I do that?

I realize using stream_context I may be able to do that but I am not entirely clear.

Thanks.

dnlcrl
  • 4,582
  • 3
  • 29
  • 39
Paras Chopra
  • 3,789
  • 4
  • 18
  • 18
  • 1
    http://php.net/manual/en/function.stream-context-create.php#89080 – Ben Jul 28 '14 at 20:56
  • 9
    This should be upvoted infinitely. There is no reason to use Curl/Guzzle or any other fancy library if you have raw PHP functionality that do the job. – Omar Abid Mar 26 '15 at 21:03

3 Answers3

610

Sending an HTTP POST request using file_get_contents is not that hard, actually : as you guessed, you have to use the $context parameter.


There's an example given in the PHP manual, at this page : HTTP context options (quoting) :

$postdata = http_build_query(
    array(
        'var1' => 'some content',
        'var2' => 'doh'
    )
);

$opts = array('http' =>
    array(
        'method'  => 'POST',
        'header'  => 'Content-Type: application/x-www-form-urlencoded',
        'content' => $postdata
    )
);

$context  = stream_context_create($opts);

$result = file_get_contents('http://example.com/submit.php', false, $context);

Basically, you have to create a stream, with the right options (there is a full list on that page), and use it as the third parameter to file_get_contents -- nothing more ;-)


As a sidenote : generally speaking, to send HTTP POST requests, we tend to use curl, which provides a lot of options an all -- but streams are one of the nice things of PHP that nobody knows about... too bad...

Volomike
  • 21,378
  • 19
  • 99
  • 188
Pascal MARTIN
  • 374,560
  • 73
  • 631
  • 650
  • 1
    Thanks. I am guessing I can insert the contents from $_POST into $postdata if I need to pass same POST params to the requested page? – Paras Chopra Mar 15 '10 at 06:49
  • 7
    I suppose you can do something like that ; but `content` must not be a PHP array : it has to be a querystring *(i.e. it must has this format : `param1=value1&param2=value2&param3=value3` )* ;; which means you'll probably have to use `http_build_query($_POST)` – Pascal MARTIN Mar 15 '10 at 06:52
  • 3
    Wonderful! I was looking for a way to pass POST data to another page which is achievable by doing `$postdata = http_build_query($_POST)`. – Liam Newmarch Nov 30 '11 at 12:20
  • 1
    intresting enough this does not work for me at all i been tryiung it for a few hours and all my requets get turned into get querys – WojonsTech Oct 02 '12 at 07:01
  • What if the parameters value are not strings but arrays or hashes etc ? – oldergod Jun 10 '13 at 06:17
  • 1
    To send multiple header values, throw them all into one string with `\r\n` line breaks - see: http://stackoverflow.com/a/2107792/404960 – rymo Jul 03 '14 at 16:08
  • Always add the option [ignore_errors => true](http://stackoverflow.com/a/6041020/1119695) to get a more cURL like result. Otherwise `file_get_contents` will **only** return `false`, if there is an HTTP error status code delivered by the server. Just in case if you are working with some kind of API, which sets HTTP error status codes and you want to analyse the received message or error details. – malisokan Dec 06 '14 at 23:07
  • To send raw XML post, change `header` to `Content-Type: text/plain` or `Content-Type: text/xml` and then set `content` to the XML. In my case, I usually don't send raw, unencrypted XML. I usually use `openssl_encrypt` with `aes-256-cbc` and a long password. But your needs may vary. – Volomike Jul 29 '16 at 20:13
  • As of 2017: No matter all comments... This original answer is working SUPER GREAT. My only issue was NOT TO USE relative path to the target file to open, but the full URL. +1 (I'm using this to get email templates in different langages) ;) – Louys Patrice Bessette Mar 20 '17 at 20:41
  • Superb - I've never seen this technique before - I used it to POST JSON to a REST API and retrieve a JSON response. – w5m Jun 28 '17 at 10:04
  • Is it possible to do this using curl? – Cristal Apr 09 '18 at 04:09
21

An alternative, you can also use fopen

$params = array('http' => array(
    'method' => 'POST',
    'content' => 'toto=1&tata=2'
));

$ctx = stream_context_create($params);
$fp = @fopen($sUrl, 'rb', false, $ctx);
if (!$fp)
{
    throw new Exception("Problem with $sUrl, $php_errormsg");
}

$response = @stream_get_contents($fp);
if ($response === false) 
{
    throw new Exception("Problem reading data from $sUrl, $php_errormsg");
}
Macbric
  • 442
  • 4
  • 10
  • For some reason, this worked for me, but the PHP official example did not. +1 for the `toto=1&tata=2` as well. I didn't use the `fopen`, however. – Michael Yaworski Jul 17 '15 at 19:09
  • 4
    @Ġiĺàɗ We don't call people 'noob' here. This is a friendly warning against such. – Daedalus Jan 26 '16 at 10:35
0
$sUrl = 'http://www.linktopage.com/login/';
$params = array('http' => array(
    'method'  => 'POST',
    'content' => 'username=admin195&password=d123456789'
));

$ctx = stream_context_create($params);
$fp = @fopen($sUrl, 'rb', false, $ctx);
if(!$fp) {
    throw new Exception("Problem with $sUrl, $php_errormsg");
}

$response = @stream_get_contents($fp);
if($response === false) {
    throw new Exception("Problem reading data from $sUrl, $php_errormsg");
}
step
  • 1,625
  • 2
  • 19
  • 35
user2525449
  • 281
  • 1
  • 2
  • 9
  • 2
    Please, try to provide an elaborated answer instead of simply copying/pasting code. – Felipe Leão Apr 06 '18 at 18:18
  • 1
    Also this is unnecessarily complicated. You can use `file_get_contents` instead of `fopen` + `stream_get_contents`. And you are not even closing the "file". See the accepted answer by @PascalMARTIN. – Martin Prikryl Sep 21 '18 at 11:20