Como postar dados em PHP usando file_get_contents?

299

Estou usando a função do PHP file_get_contents()para buscar o conteúdo de uma URL e depois processo os cabeçalhos pela variável $http_response_header.

Agora, o problema é que alguns dos URLs precisam que alguns dados sejam postados no URL (por exemplo, páginas de login).

Como faço isso?

Eu percebo que usando stream_context eu posso fazer isso, mas não sou totalmente claro.

Obrigado.

Paras Chopra
fonte
8
Isso deve ser votado infinitamente. Não há razão para usar o Curl / Guzzle ou qualquer outra biblioteca sofisticada se você tiver a funcionalidade PHP bruta que faz o trabalho.
Omar Abid

Respostas:

589

Enviar uma solicitação HTTP POST usando file_get_contentsnão é tão difícil, na verdade: como você adivinhou, é necessário usar o $contextparâmetro


Há um exemplo dado no manual do PHP, nesta página: Opções de contexto HTTP (citando) :

$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);

Basicamente, você precisa criar um fluxo, com as opções corretas (há uma lista completa nessa página) e usá-lo como o terceiro parâmetro para file_get_contents- nada mais ;-)


Como nota de rodapé: de um modo geral, para enviar solicitações HTTP POST, tendemos a usar curl, que oferece muitas opções - mas os fluxos são uma das coisas boas do PHP que ninguém conhece ... muito ruim .. .

Pascal MARTIN
fonte
1
Obrigado. Acho que posso inserir o conteúdo de $ _POST no $ postdata se precisar passar os mesmos parâmetros do POST para a página solicitada?
Paras Chopra
6
Suponho que você possa fazer algo assim; mas contentnão deve ser uma matriz PHP: tem que ser um querystring (isto é, deve tem o seguinte formato: param1=value1&param2=value2&param3=value3) ;; que significa que você provavelmente vai ter que usarhttp_build_query($_POST)
Pascal MARTIN
2
Maravilhoso! Eu estava procurando uma maneira de passar dados do POST para outra página que é possível fazer isso $postdata = http_build_query($_POST).
Liam Newmarch
1
intresting suficiente Isso não funciona para mim em tudo i sido tryiung-lo por algumas horas e todos os meus requets se transformou em querys get
WojonsTech
1
Para enviar vários valores de cabeçalho, jogá-los todos em uma corda com \r\nquebras de linha - ver: stackoverflow.com/a/2107792/404960
RYMO
20

Uma alternativa, você também pode usar 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
fonte
Por alguma razão, isso funcionou para mim, mas o exemplo oficial do PHP não. +1 para o toto=1&tata=2também. Eu não usei o fopen, no entanto.
Michael Yaworski 17/07/2015
4
@ Ġiĺàɗ Não chamamos as pessoas de 'noob' aqui. Este é um aviso amigável contra isso.
Daedalus
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");
}
user2525449
fonte
2
Por favor, tente fornecer uma resposta elaborada em vez de simplesmente copiar / colar código.
Felipe Leão
1
Além disso, isso é desnecessariamente complicado. Você pode usar em file_get_contentsvez de fopen+ stream_get_contents. E você nem está fechando o "arquivo". Veja a resposta aceita por @PascalMARTIN.
Martin Prikryl