Esta é uma pergunta útil para pessoas que desejam criar APIs RESTful. A maioria não sabe como acessar os dados de entrada brutos enviados para seus scripts, pois não estão disponíveis na $_POSTsuperglobal. Isso também é (especialmente) verdadeiro no caso de solicitações PUT, pois o PHP não possui superglobal correspondente.
Vale ressaltar que o nome $ _POST é enganoso, pois nenhum tipo de dado de uma solicitação POST estará lá, mas apenas quando o tipo de conteúdo for application / x-www-form-urlencoded ou multipart / form-data
Petruza
Respostas:
549
Para acessar o corpo da entidade de uma solicitação POST ou PUT (ou qualquer outro método HTTP):
$entityBody = file_get_contents('php://input');
Além disso, a STDINconstante é um fluxo já aberto para php://input, portanto, você pode alternativamente:
php: // input é um fluxo somente leitura que permite ler dados brutos do corpo da solicitação. No caso de solicitações POST, é preferível usar php: // input em vez de $HTTP_RAW_POST_DATAnão depender de diretivas especiais do php.ini. Além disso, nos casos em que
$HTTP_RAW_POST_DATAnão é preenchido por padrão, é uma alternativa potencialmente menos intensiva em memória para ativar always_populate_raw_post_data. php: // input não está disponível com enctype = "multipart / form-data".
Especificamente, você deve observar que o php://inputfluxo, independentemente de como você o acessa em uma SAPI da web, não é procurável . Isso significa que ele só pode ser lido uma vez. Se você estiver trabalhando em um ambiente em que grandes corpos de entidades HTTP são carregados rotineiramente, convém manter a entrada em sua forma de fluxo (em vez de armazená-la em buffer, como no primeiro exemplo acima).
Para manter o recurso de fluxo, algo como isto pode ser útil:
php://temppermite que você gerencie o consumo de memória, pois ele mudará de maneira transparente para o armazenamento do sistema de arquivos após o armazenamento de uma certa quantidade de dados (2M por padrão). Esse tamanho pode ser manipulado no arquivo php.ini ou anexando /maxmemory:NN, onde NNestá a quantidade máxima de dados a serem armazenados na memória antes de usar um arquivo temporário, em bytes.
Obviamente, a menos que você tenha um bom motivo para procurar no fluxo de entrada, não precisará dessa funcionalidade em um aplicativo da web. A leitura do corpo da entidade de solicitação HTTP uma vez é geralmente suficiente - não deixe os clientes esperando o dia todo enquanto o aplicativo descobre o que fazer.
Observe que php: // input não está disponível para solicitações que especificam um Content-Type: multipart/form-datacabeçalho ( enctype="multipart/form-data"em formulários HTML). Isso resulta do PHP já ter analisado os dados do formulário no $_POSTsuperglobal.
Por favor, note que AFAICS, o fluxo STDIN não está disponível em sistemas que executam o PHP usando CGI, ou seja, através mod_fcgid ou mod_fastcgi etc.
Scy
mas, estou passando a variável (como formulário-dados) com a solicitação, como posso acessar o valor especificado? entityBody "
Anvar Pk
de acordo com o meu teste, esta php://inputestá vazia para application/x-www-form-urlencodedo tipo de conteúdo, bem como (para além multipart/form-data)
YakovL
6
Para expandir a resposta do @ scy: STDIN não está disponível, mas php://inputestá. Então, enquanto as configurações de CGI (rápidas) stream_get_contents(STDIN)não funcionarem, funcionará file_get_contents("php://input").
Nesse cenário, agora você precisa percorrer a $datamatriz associativa para verificar se cada valor está codificado da maneira que você deseja. A maneira de ver as coisas "fluxo para tipo de dados" pode ser simplista, mas pode não ser tão eficiente quanto lidar com a codificação no "formulário de fluxo" usando um filtro de fluxo. Se você não está lidando com problemas de codificação e simplesmente limpando e validando, está faltando uma etapa.
Anthony Rutledge
13
Uma possível razão para um vazio $_POSTé que a solicitação não está POST, ou não está POSTmais ... Ela pode ter começado como postagem, mas encontrou um 301ou 302redirecionado para algum lugar, para o qual foi alternada GET!
Inspecione $_SERVER['REQUEST_METHOD']para verificar se é esse o caso.
Esta pergunta foi feita no contexto do desenvolvimento de uma plataforma API REST.
Itay Moav -Malimovka 16/03/16
Eu não tenho certeza do que você quer dizer? Uma API REST pode também encontrar redirecionamentos no caminho, esse é o problema que tive.
Legolas
Eu quis dizer que, quando fiz a pergunta, não estava tentando resolver um bug, mas tentando descobrir como desenvolvê-lo.
Itay Moav -Malimovka 17/03
3
Essa dica salvou meu dia. o servidor de recebimento foi reconfigurado para redirecionar para https, que quebrou alguns clientes da API.
DesertEagle 15/02
Na verdade, o meu pedido foi, POSTmas depois de inspecionar, estava mostrando que sim GET. Depois de adicionar um /no final do meu URL, ele começou a mostrar POST. Esquisito!
function getPost(){if(!empty($_POST)){// when using application/x-www-form-urlencoded or multipart/form-data as the HTTP Content-Type in the request// NOTE: if this is the case and $_POST is empty, check the variables_order in php.ini! - it must contain the letter Preturn $_POST;}// when using application/json as the HTTP Content-Type in the request
$post = json_decode(file_get_contents('php://input'),true);if(json_last_error()== JSON_ERROR_NONE){return $post;}return[];}
print_r(getPost());
O que esse bit de lógica está faltando é um teste do valor encontrado no cabeçalho Content-Type. Não se segue que, apenas porque $ _POST está vazio, o JSON deve ter sido enviado ou, se json_last_error() == JSON_ERROR_NONEestiver false, que uma matriz vazia deve ser retornada. E se alguém tiver enviado XML ou YAML? Adicione um teste para o tipo de conteúdo e vá a partir daí.
Anthony Rutledge
Além disso, o método de solicitação HTTP pode levar em consideração se você deseja aceitar dados de entrada. Veja a $_SERVERsuperglobal para obter valores úteis a serem verificados.
$_POST
superglobal. Isso também é (especialmente) verdadeiro no caso de solicitações PUT, pois o PHP não possui superglobal correspondente.Respostas:
Para acessar o corpo da entidade de uma solicitação POST ou PUT (ou qualquer outro método HTTP):
Além disso, a
STDIN
constante é um fluxo já aberto paraphp://input
, portanto, você pode alternativamente:Na entrada manual do PHP nos documentos de fluxos de E / S :
Especificamente, você deve observar que o
php://input
fluxo, independentemente de como você o acessa em uma SAPI da web, não é procurável . Isso significa que ele só pode ser lido uma vez. Se você estiver trabalhando em um ambiente em que grandes corpos de entidades HTTP são carregados rotineiramente, convém manter a entrada em sua forma de fluxo (em vez de armazená-la em buffer, como no primeiro exemplo acima).Para manter o recurso de fluxo, algo como isto pode ser útil:
php://temp
permite que você gerencie o consumo de memória, pois ele mudará de maneira transparente para o armazenamento do sistema de arquivos após o armazenamento de uma certa quantidade de dados (2M por padrão). Esse tamanho pode ser manipulado no arquivo php.ini ou anexando/maxmemory:NN
, ondeNN
está a quantidade máxima de dados a serem armazenados na memória antes de usar um arquivo temporário, em bytes.Obviamente, a menos que você tenha um bom motivo para procurar no fluxo de entrada, não precisará dessa funcionalidade em um aplicativo da web. A leitura do corpo da entidade de solicitação HTTP uma vez é geralmente suficiente - não deixe os clientes esperando o dia todo enquanto o aplicativo descobre o que fazer.
Observe que php: // input não está disponível para solicitações que especificam um
Content-Type: multipart/form-data
cabeçalho (enctype="multipart/form-data"
em formulários HTML). Isso resulta do PHP já ter analisado os dados do formulário no$_POST
superglobal.fonte
php://input
está vazia paraapplication/x-www-form-urlencoded
o tipo de conteúdo, bem como (para alémmultipart/form-data
)php://input
está. Então, enquanto as configurações de CGI (rápidas)stream_get_contents(STDIN)
não funcionarem, funcionaráfile_get_contents("php://input")
.valor de retorno na matriz
fonte
$data
matriz associativa para verificar se cada valor está codificado da maneira que você deseja. A maneira de ver as coisas "fluxo para tipo de dados" pode ser simplista, mas pode não ser tão eficiente quanto lidar com a codificação no "formulário de fluxo" usando um filtro de fluxo. Se você não está lidando com problemas de codificação e simplesmente limpando e validando, está faltando uma etapa.Uma possível razão para um vazio
$_POST
é que a solicitação não estáPOST
, ou não estáPOST
mais ... Ela pode ter começado como postagem, mas encontrou um301
ou302
redirecionado para algum lugar, para o qual foi alternadaGET
!Inspecione
$_SERVER['REQUEST_METHOD']
para verificar se é esse o caso.Consulte https://stackoverflow.com/a/19422232/109787 para obter uma boa discussão sobre por que isso não deveria acontecer, mas ainda acontece.
fonte
POST
mas depois de inspecionar, estava mostrando que simGET
. Depois de adicionar um/
no final do meu URL, ele começou a mostrar POST. Esquisito!Verifique a
$HTTP_RAW_POST_DATA
variávelfonte
php://input
.$HTTP_RAW_POST_DATA
não está disponível comenctype="multipart/form-data"
.Se você instalou a extensão HTTP PECL, poderá usar a
http_get_request_body()
função para obter dados do corpo como uma sequência.fonte
Se você possui a extensão pecl / http instalada, também pode usar:
fonte
fonte
json_last_error() == JSON_ERROR_NONE
estiverfalse
, que uma matriz vazia deve ser retornada. E se alguém tiver enviado XML ou YAML? Adicione um teste para o tipo de conteúdo e vá a partir daí.$_SERVER
superglobal para obter valores úteis a serem verificados.http_get_request_body()
foi feito explicitamente para obter o corpoPUT
e asPOST
solicitações de acordo com a documentação http://php.net/manual/fa/function.http-get-request-body.phpfonte