Fui orientado a usar o método em php://input
vez de $_POST
interagir com solicitações Ajax do JQuery. O que eu não entendo são os benefícios de usar isso vs o método global de $_POST
or $_GET
.
Fui orientado a usar o método em php://input
vez de $_POST
interagir com solicitações Ajax do JQuery. O que eu não entendo são os benefícios de usar isso vs o método global de $_POST
or $_GET
.
Respostas:
A razão é que php://input
retorna todos os dados brutos após os cabeçalhos HTTP da solicitação, independentemente do tipo de conteúdo.
O superglobal do PHP $_POST
apenas deve agrupar dados que sejam
application/x-www-form-urlencoded
(tipo de conteúdo padrão para postagens simples) oumultipart/form-data
(usado principalmente para upload de arquivos)Isso ocorre porque esses são os únicos tipos de conteúdo que devem ser suportados pelos agentes do usuário . Portanto, o servidor e o PHP tradicionalmente não esperam receber nenhum outro tipo de conteúdo (o que não significa que não possam).
Portanto, se você simplesmente POSTAR um bom e velho HTML form
, a solicitação se parece com isso:
POST /page.php HTTP/1.1
key1=value1&key2=value2&key3=value3
Mas se você trabalha muito com o Ajax, esse probaby também inclui a troca de dados mais complexos com tipos (string, int, bool) e estruturas (matrizes, objetos); portanto, na maioria dos casos, o JSON é a melhor opção. Mas uma solicitação com uma carga JSON se pareceria com isso:
POST /page.php HTTP/1.1
{"key1":"value1","key2":"value2","key3":"value3"}
O conteúdo agora seria application/json
(ou pelo menos nenhum dos mencionados acima), portanto, o $_POST
ww-wrapper do PHP ainda não sabe como lidar com isso (ainda).
Os dados ainda estão lá, você simplesmente não pode acessá-los através do wrapper. Portanto, você deve buscá-lo no formato bruto com file_get_contents('php://input')
( desde que não seja multipart/form-data
codificado) ).
Também é assim que você acessaria dados XML ou qualquer outro tipo de conteúdo não padrão.
application/json
como fonte de dados válida para o $_POST
array. E há até pedidos publicados especificamente para esse suporte.
php://input
pode fornecer os bytes brutos dos dados. Isso é útil se os dados POSTed forem uma estrutura codificada em JSON, que geralmente é o caso de uma solicitação AJAX POST.
Aqui está uma função para fazer exatamente isso:
/**
* Returns the JSON encoded POST data, if any, as an object.
*
* @return Object|null
*/
private function retrieveJsonPostData()
{
// get the raw POST data
$rawData = file_get_contents("php://input");
// this returns null if not valid json
return json_decode($rawData);
}
A $_POST
matriz é mais útil quando você manipula dados de valor-chave de um formulário, enviado por um POST tradicional. Isso funciona apenas se os dados do POSTed estiverem em um formato reconhecido, normalmente application/x-www-form-urlencoded
(consulte http://www.w3.org/TR/html4/interact/forms.html#h-17.13.4 para obter detalhes).
true
como o segundo parâmetro json_decode
, ele retornará uma matriz associativa.
Se os dados da postagem estiverem malformados, $ _POST não conterá nada. No entanto, php: // input terá a string malformada.
Por exemplo, existem alguns aplicativos ajax que não formam a sequência correta de valor-chave de postagem para fazer upload de um arquivo e apenas despejam todo o arquivo como dados de postagem, sem nomes de variáveis ou qualquer coisa. $ _POST estará vazio, $ _FILES também vazio e php: // input conterá o arquivo exato, escrito como uma string.
O PHP não foi projetado para fornecer explicitamente uma interface REST pura (GET, POST, PUT, PATCH, DELETE) para lidar com solicitações HTTP .
No entanto, os $_POST
, $_GET
e $_FILES
superglobals , e a funçãofilter_input_array()
são muito úteis para as necessidades / leigos da pessoa média.
A principal vantagem oculta de $_POST
(e $_GET
) é que seus dados de entrada são codificados automaticamente pelo PHP . Você nunca pensa em fazê-lo, especialmente para parâmetros de sequência de consulta em uma solicitação GET padrão.
Dito isto, à medida que você avança no seu conhecimento de programação e deseja usar o XmlHttpRequest
objeto JavaScript (jQuery para alguns), você vê a limitação desse esquema.
$_POST
limita você ao uso de dois tipos de mídia no Content-Type
cabeçalho HTTP :
application/x-www-form-urlencoded
emultipart/form-data
Portanto, se você deseja enviar valores de dados para o PHP no servidor e mostrá-los na $_POST
superglobal , deve codificá- los no lado do cliente e enviar os dados como pares de chave / valor - uma etapa inconveniente para iniciantes (especialmente ao tentar descobrir se partes diferentes do URL exigem formas diferentes de codificação de URL: normal, bruto, etc.).
Para todos os usuários do jQuery, o $.ajax()
método é converter seu JSON em pares de chave / valor codificado em URL antes de transmiti-los ao servidor. Você pode substituir esse comportamento, definindo processData: false
. Basta ler a documentação $ .ajax () e não se esqueça de enviar o tipo de mídia correto no cabeçalho Content-Type.
Normalmente, se você estiver executando solicitações HTTP normais e síncronas (quando a página inteira redesenhar) com um formulário HTML, o agente do usuário (navegador da Web) codificará os dados do formulário para você. Se você deseja fazer solicitações HTTP assíncronas usando o XmlHttpRequest
objeto, é necessário criar uma string codificada em url e enviá-la, se desejar que esses dados sejam exibidos na $_POST
superglobal .
A conversão de uma matriz ou objeto JavaScript em uma string codificada em url incomoda muitos desenvolvedores (mesmo com novas APIs como Form Data ). Eles prefeririam apenas enviar JSON, e seria mais eficiente o código do cliente fazer isso.
Lembre-se (wink, wink), o desenvolvedor da Web comum não aprende a usar o XmlHttpRequest
objeto diretamente, funções globais, funções de string, funções de array e expressões regulares como você e eu ;-). Urlencoding para eles é um pesadelo. ;-)
A falta de manipulação intuitiva de XML e JSON do PHP desativa muitas pessoas. Você pensaria que seria parte do PHP agora (suspiro).
XML, JSON e YAML todos têm tipos de mídia que podem ser colocados em um Content-Type
cabeçalho HTTP .
Veja quantos tipos de mídia (anteriormente, tipos MIME) são definidos pela IANA.
Veja quantos cabeçalhos HTTP existem.
Usando o php://input
fluxo permite contornar o nível de abstração de babás / mãos que o PHP impôs ao mundo. :-) Com grandes poderes vem grandes responsabilidades!
Agora, antes de lidar com valores de dados transmitidos php://input
, você deve / deve fazer algumas coisas.
Ah, ah! Sim, você pode querer que o fluxo de dados enviado ao seu aplicativo seja codificado em UTF-8, mas como você pode saber se é ou não?
php://input
.Você tentará manipular dados de fluxo sem saber quanto há primeiro? Essa é uma péssima ideia . Você não pode confiar exclusivamente no Content-Length
cabeçalho HTTP para obter orientação sobre o tamanho da entrada transmitida porque pode ser falsificada.
Você vai precisar de:
Você tentará converter dados de fluxo em UTF-8 sem conhecer a codificação atual do fluxo? Quão? O filtro de fluxo iconv ( exemplo de filtro de fluxo iconv ) parece querer uma codificação inicial e final, como esta.
'convert.iconv.ISO-8859-1/UTF-8'
Assim, se você tiver consciência, precisará de:
( Atualização : 'convert.iconv.UTF-8/UTF-8'
forçará tudo para UTF-8, mas você ainda precisará considerar os caracteres que a biblioteca iconv talvez não saiba traduzir. Em outras palavras, você precisa definir como agir quando um personagem não puder ser traduzido : 1) Insira um caractere fictício, 2) Fail / throw e exceção).
Você não pode confiar exclusivamente no Content-Encoding
cabeçalho HTTP , pois isso pode indicar algo como compactação, como a seguir. Não é disso que você deseja tomar uma decisão em relação ao iconv.
Content-Encoding: gzip
Parte I: Solicitação HTTP Relacionada
Parte II: Dados relacionados ao fluxo
Parte III: Relacionado ao Tipo de Dados
(Lembre-se de que os dados ainda podem ser uma string codificada em URL que você deve analisar e decodificar em URL).
Parte IV: Relacionado ao Valor dos Dados
Filtre os dados de entrada.
Valide os dados de entrada.
A $_POST
superglobal, juntamente com as configurações do php.ini para limites de entrada, são mais simples para o leigo. No entanto, lidar com a codificação de caracteres é muito mais intuitivo e eficiente ao usar fluxos, porque não há necessidade de passar por superglobais (ou matrizes, geralmente) para verificar os valores de entrada para a codificação adequada.
Então, eu escrevi uma função que obteria os dados POST do fluxo de entrada php: // .
Portanto, o desafio aqui foi mudar para o método de solicitação PUT, DELETE OR PATCH e ainda obter os dados de postagem enviados com essa solicitação.
Estou compartilhando isso talvez para alguém com um desafio semelhante. A função abaixo é o que eu criei e funciona. Espero que ajude!
/**
* @method Post getPostData
* @return array
*
* Convert Content-Disposition to a post data
*/
function getPostData() : array
{
// @var string $input
$input = file_get_contents('php://input');
// continue if $_POST is empty
if (strlen($input) > 0 && count($_POST) == 0 || count($_POST) > 0) :
$postsize = "---".sha1(strlen($input))."---";
preg_match_all('/([-]{2,})([^\s]+)[\n|\s]{0,}/', $input, $match);
// update input
if (count($match) > 0) $input = preg_replace('/([-]{2,})([^\s]+)[\n|\s]{0,}/', '', $input);
// extract the content-disposition
preg_match_all("/(Content-Disposition: form-data; name=)+(.*)/m", $input, $matches);
// let's get the keys
if (count($matches) > 0 && count($matches[0]) > 0)
{
$keys = $matches[2];
foreach ($keys as $index => $key) :
$key = trim($key);
$key = preg_replace('/^["]/','',$key);
$key = preg_replace('/["]$/','',$key);
$key = preg_replace('/[\s]/','',$key);
$keys[$index] = $key;
endforeach;
$input = preg_replace("/(Content-Disposition: form-data; name=)+(.*)/m", $postsize, $input);
$input = preg_replace("/(Content-Length: )+([^\n]+)/im", '', $input);
// now let's get key value
$inputArr = explode($postsize, $input);
// @var array $values
$values = [];
foreach ($inputArr as $index => $val) :
$val = preg_replace('/[\n]/','',$val);
if (preg_match('/[\S]/', $val)) $values[$index] = trim($val);
endforeach;
// now combine the key to the values
$post = [];
// @var array $value
$value = [];
// update value
foreach ($values as $i => $val) $value[] = $val;
// push to post
foreach ($keys as $x => $key) $post[$key] = isset($value[$x]) ? $value[$x] : '';
if (is_array($post)) :
$newPost = [];
foreach ($post as $key => $val) :
if (preg_match('/[\[]/', $key)) :
$k = substr($key, 0, strpos($key, '['));
$child = substr($key, strpos($key, '['));
$child = preg_replace('/[\[|\]]/','', $child);
$newPost[$k][$child] = $val;
else:
$newPost[$key] = $val;
endif;
endforeach;
$_POST = count($newPost) > 0 ? $newPost : $post;
endif;
}
endif;
// return post array
return $_POST;
}
Exemplo simples de como usá-lo
<?php
if(!isset($_POST) || empty($_POST)) {
?>
<form name="form1" method="post" action="">
<input type="text" name="textfield"><br />
<input type="submit" name="Submit" value="submit">
</form>
<?php
} else {
$example = file_get_contents("php://input");
echo $example; }
?>