Il s'agit d'une question utile pour les personnes souhaitant créer des API RESTful. La plupart ne savent pas comment accéder aux données d'entrée brutes soumises à leurs scripts car elles ne sont pas disponibles via le $_POSTsuperglobal. Cela est également (particulièrement) vrai dans le cas des requêtes PUT, car PHP n'a pas de superglobal correspondant.
Il convient de noter que le nom $ _POST est trompeur, car aucun type de données provenant d'une demande POST ne sera présent, mais uniquement lorsque le type de contenu est application / x-www-form-urlencoded ou multipart / form-data
Petruza
Réponses:
549
Pour accéder au corps d'entité d'une demande POST ou PUT (ou à toute autre méthode HTTP):
$entityBody = file_get_contents('php://input');
De plus, la STDINconstante est un flux déjà ouvert vers php://input, vous pouvez donc également faire:
php: // input est un flux en lecture seule qui vous permet de lire les données brutes du corps de la requête. Dans le cas des requêtes POST, il est préférable d'utiliser l' entrée php: // au lieu de $HTTP_RAW_POST_DATAcela car cela ne dépend pas de directives php.ini spéciales. De plus, pour les cas où il
$HTTP_RAW_POST_DATAn'est pas renseigné par défaut, il s'agit d'une alternative potentiellement moins gourmande en mémoire à l'activation de always_populate_raw_post_data. php: // entrée n'est pas disponible avec enctype = "multipart / form-data".
Plus précisément, vous voudrez noter que le php://inputflux, quelle que soit la façon dont vous y accédez dans un SAPI Web, n'est pas recherché . Cela signifie qu'il ne peut être lu qu'une seule fois. Si vous travaillez dans un environnement où de grands corps d'entités HTTP sont régulièrement téléchargés, vous souhaiterez peut-être conserver l'entrée sous sa forme de flux (plutôt que de la mettre en mémoire tampon comme dans le premier exemple ci-dessus).
Pour maintenir la ressource de flux, quelque chose comme ceci peut être utile:
php://tempvous permet de gérer la consommation de mémoire car il basculera de manière transparente vers le stockage du système de fichiers après le stockage d'une certaine quantité de données (2 Mo par défaut). Cette taille peut être manipulée dans le fichier php.ini ou en ajoutant /maxmemory:NN, où NNest la quantité maximale de données à conserver en mémoire avant d'utiliser un fichier temporaire, en octets.
Bien sûr, à moins d'avoir une très bonne raison de rechercher sur le flux d'entrée, vous ne devriez pas avoir besoin de cette fonctionnalité dans une application Web. La lecture du corps de l'entité de demande HTTP une fois suffit généralement - ne laissez pas les clients attendre toute la journée pendant que votre application trouve quoi faire.
Notez que l'entrée php: // n'est pas disponible pour les demandes spécifiant un en- Content-Type: multipart/form-datatête ( enctype="multipart/form-data"dans les formulaires HTML). Cela résulte du fait que PHP a déjà analysé les données du formulaire dans le $_POSTsuperglobal.
Veuillez noter que afaics, le flux STDIN n'est pas disponible sur les systèmes exécutant PHP utilisant CGI, c'est-à-dire via mod_fcgid ou mod_fastcgi etc.
scy
mais, je transmets une variable (sous forme de données de formulaire) à la demande, comment puis-je accéder à la valeur spécifiée, je transmets grant_type = mot de passe et nom d'utilisateur = utilisateur et mot de passe = passer en tant que corps de données de formulaire avec la demande, comment vais-je obtenir grant_type de "$ entityBody "
Anvar Pk
selon mon test, ceci php://inputest également vide pour le application/x-www-form-urlencodedtype de contenu (en plus multipart/form-data)
YakovL
6
Pour développer la réponse de @ scy: STDIN n'est pas disponible, mais l' php://inputest. Ainsi, alors que les configurations CGI (rapides) stream_get_contents(STDIN)ne fonctionneront pas, elles le file_get_contents("php://input")seront.
Dans ce scénario, vous devez maintenant parcourir le $datatableau associatif pour vérifier si chaque valeur est codée comme vous le souhaitez. La façon de voir les choses de «flux vers type de données» peut être simpliste, mais elle peut ne pas être aussi efficace que de traiter le codage sous la «forme de flux» à l'aide d'un filtre de flux. Si vous ne gérez pas les problèmes d'encodage et que vous désinfectez et validez simplement, il vous manque une étape.
Anthony Rutledge
13
Une raison possible pour un vide $_POSTest que la demande ne l'est pas POST, ou POSTplus ... Elle peut avoir commencé en tant que publication, mais a rencontré un 301ou 302rediriger quelque part, qui est basculé vers GET!
Inspectez $_SERVER['REQUEST_METHOD']pour vérifier si c'est le cas.
Cette question a été posée dans le cadre du développement d'une plateforme api REST.
Itay Moav -Malimovka
Je ne sais pas ce que tu veux dire? Une API REST pourrait tout aussi bien trouver des redirections sur son chemin, c'est le problème que j'ai eu.
Legolas
Je voulais dire quand j'ai posé la question, je n'essayais pas de résoudre un bogue, mais plutôt d'essayer de comprendre comment le développer.
Itay Moav -Malimovka
3
cette allusion m'a sauvé la journée. le serveur de réception a été reconfiguré pour rediriger vers https qui a cassé certains clients API.
DesertEagle
En fait, ma demande était, POSTmais après inspection, elle montrait que c'était le cas GET. Une fois que j'ai ajouté un /à la fin de mon URL, il a commencé à afficher POST. Bizarre!
La méthode préférée pour accéder aux données POST brutes est php://input. $HTTP_RAW_POST_DATAn'est pas disponible avec enctype="multipart/form-data".
nullité
38
Cette fonctionnalité a été obsolète en PHP 5.6.0 et supprimée en PHP 7.0.0.
Charles
3
Si vous avez installé l'extension HTTP PECL, vous pouvez utiliser la http_get_request_body()fonction pour obtenir les données du corps sous forme de chaîne.
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());
Ce peu de logique qui manque est un test de la valeur trouvée dans l'en-tête Content-Type. Il ne suit pas que juste parce que $ _POST est vide que JSON doit avoir été soumis, ou que si json_last_error() == JSON_ERROR_NONEest false, qu'un tableau vide doit être retourné. Que faire si quelqu'un a soumis du XML ou du YAML? Ajoutez un test pour le Content-Type et continuez à partir de là.
Anthony Rutledge
De plus, la méthode de requête HTTP peut prendre en compte la détermination de l'acceptation des données d'entrée. Voir le $_SERVERsuperglobal pour les valeurs utiles à vérifier.
$_POST
superglobal. Cela est également (particulièrement) vrai dans le cas des requêtes PUT, car PHP n'a pas de superglobal correspondant.Réponses:
Pour accéder au corps d'entité d'une demande POST ou PUT (ou à toute autre méthode HTTP):
De plus, la
STDIN
constante est un flux déjà ouvert versphp://input
, vous pouvez donc également faire:À partir de l' entrée manuelle PHP sur les documents de flux d'E / S :
Plus précisément, vous voudrez noter que le
php://input
flux, quelle que soit la façon dont vous y accédez dans un SAPI Web, n'est pas recherché . Cela signifie qu'il ne peut être lu qu'une seule fois. Si vous travaillez dans un environnement où de grands corps d'entités HTTP sont régulièrement téléchargés, vous souhaiterez peut-être conserver l'entrée sous sa forme de flux (plutôt que de la mettre en mémoire tampon comme dans le premier exemple ci-dessus).Pour maintenir la ressource de flux, quelque chose comme ceci peut être utile:
php://temp
vous permet de gérer la consommation de mémoire car il basculera de manière transparente vers le stockage du système de fichiers après le stockage d'une certaine quantité de données (2 Mo par défaut). Cette taille peut être manipulée dans le fichier php.ini ou en ajoutant/maxmemory:NN
, oùNN
est la quantité maximale de données à conserver en mémoire avant d'utiliser un fichier temporaire, en octets.Bien sûr, à moins d'avoir une très bonne raison de rechercher sur le flux d'entrée, vous ne devriez pas avoir besoin de cette fonctionnalité dans une application Web. La lecture du corps de l'entité de demande HTTP une fois suffit généralement - ne laissez pas les clients attendre toute la journée pendant que votre application trouve quoi faire.
Notez que l'entrée php: // n'est pas disponible pour les demandes spécifiant un en-
Content-Type: multipart/form-data
tête (enctype="multipart/form-data"
dans les formulaires HTML). Cela résulte du fait que PHP a déjà analysé les données du formulaire dans le$_POST
superglobal.la source
php://input
est également vide pour leapplication/x-www-form-urlencoded
type de contenu (en plusmultipart/form-data
)php://input
est. Ainsi, alors que les configurations CGI (rapides)stream_get_contents(STDIN)
ne fonctionneront pas, elles lefile_get_contents("php://input")
seront.retourne la valeur dans le tableau
la source
$data
tableau associatif pour vérifier si chaque valeur est codée comme vous le souhaitez. La façon de voir les choses de «flux vers type de données» peut être simpliste, mais elle peut ne pas être aussi efficace que de traiter le codage sous la «forme de flux» à l'aide d'un filtre de flux. Si vous ne gérez pas les problèmes d'encodage et que vous désinfectez et validez simplement, il vous manque une étape.Une raison possible pour un vide
$_POST
est que la demande ne l'est pasPOST
, ouPOST
plus ... Elle peut avoir commencé en tant que publication, mais a rencontré un301
ou302
rediriger quelque part, qui est basculé versGET
!Inspectez
$_SERVER['REQUEST_METHOD']
pour vérifier si c'est le cas.Voir https://stackoverflow.com/a/19422232/109787 pour une bonne discussion sur la raison pour laquelle cela ne devrait pas se produire, mais se produit toujours.
la source
POST
mais après inspection, elle montrait que c'était le casGET
. Une fois que j'ai ajouté un/
à la fin de mon URL, il a commencé à afficher POST. Bizarre!Vérifiez la
$HTTP_RAW_POST_DATA
variablela source
php://input
.$HTTP_RAW_POST_DATA
n'est pas disponible avecenctype="multipart/form-data"
.Si vous avez installé l'extension HTTP PECL, vous pouvez utiliser la
http_get_request_body()
fonction pour obtenir les données du corps sous forme de chaîne.la source
Si vous avez installé l'extension pecl / http , vous pouvez également utiliser ceci:
la source
la source
json_last_error() == JSON_ERROR_NONE
estfalse
, qu'un tableau vide doit être retourné. Que faire si quelqu'un a soumis du XML ou du YAML? Ajoutez un test pour le Content-Type et continuez à partir de là.$_SERVER
superglobal pour les valeurs utiles à vérifier.http_get_request_body()
a été explicitement faite pour obtenir le corps dePUT
et lesPOST
demandes selon la documentation http://php.net/manual/fa/function.http-get-request-body.phpla source