Tout d'abord, une vérité de base sur PHP.
PHP n'a pas été conçu pour vous donner explicitement une interface de type REST (GET, POST, PUT, PATCH, DELETE) pour gérer les requêtes HTTP. .
Toutefois, le $_SERVER
, $_COOKIE
, $_POST
, $_GET
et $_FILES
superglobales et la fonction filter_input_array()
sont très utiles pour les besoins de la personne moyenne / du profane.
L'avantage caché numéro un de $_POST
(et $_GET
) est que vos données d'entrée sont url-décodé automatiquement par PHP . On ne pense même pas à devoir le faire, surtout pour les paramètres de chaîne de requête dans un système standard. GET
ou les données du corps HTTP soumises avec une requête POST
demande.
Autres méthodes de requête HTTP
Ceux qui étudient le protocole HTTP sous-jacent et ses différentes méthodes de requête comprennent qu'il existe de nombreuses méthodes de requête HTTP, y compris la méthode souvent citée en référence. PUT
, PATCH
(non utilisé dans Apigee de Google), et DELETE
.
En PHP, il n'y a pas de superglobales ou de fonctions de filtre d'entrée pour obtenir les données du corps de la requête HTTP lorsque POST
n'est pas utilisé. Que doivent faire les disciples de Roy Fielding ? ;-)
Cependant, lorsque vous en apprenez davantage ...
Ceci étant dit, lorsque vous avancez dans votre connaissance de la programmation PHP et que vous souhaitez utiliser les fonctionnalités de JavaScript XmlHttpRequest
(jQuery pour certains), vous verrez les limites de ce système.
$_POST
vous limite à l'utilisation de deux types de médias dans le protocole HTTP. Content-Type
en-tête :
-
application/x-www-form-urlencoded
et
multipart/form-data
_Ainsi, si vous souhaitez envoyer des valeurs de données à PHP sur le serveur, et qu'elles apparaissent dans le fichier $_POST
superglobal_ alors vous devez urlencode du côté client et envoyer ces données sous forme de paires clé/valeur - une étape peu pratique pour les novices (surtout lorsqu'il s'agit de déterminer si les différentes parties de l'URL nécessitent différentes formes de codage url : normal, brut, etc ).
Pour tous les utilisateurs de jQuery, la fonction $.ajax()
convertit votre JSON en paires clé/valeur codées par URL avant de les transmettre au serveur. Vous pouvez remplacer ce comportement en définissant processData: false
. Il suffit de lire le Documentation de $.ajax() et n'oubliez pas d'envoyer le bon type de média dans l'en-tête Content-Type.
php://input, mais ...
Même si vous utilisez php://input
au lieu de $_POST
pour votre HTTP POST
les données du corps de la demande, il ne fonctionne pas avec un HTTP Content-Type
de multipart/form-data
Il s'agit du type de contenu que vous utilisez sur un formulaire HTML lorsque vous souhaitez autoriser le téléchargement de fichiers !
<form enctype="multipart/form-data" accept-charset="utf-8" action="post">
<input type="file" name="resume">
</form>
Par conséquent, dans le PHP traditionnel, pour traiter une diversité de types de contenu à partir d'un HTTP POST
vous apprendrez à utiliser $_POST
o filter_input_array(POST)
, $_FILES
et php://input
. Il n'y a aucun moyen d'utiliser une seule source d'entrée universelle pour HTTP POST
en PHP.
Vous ne pouvez pas obtenir de fichiers par $_POST
, filter_input_array(POST)
ou php://input
et vous ne pouvez pas obtenir JSON/XML/YAML dans les deux cas. filter_input_array(POST)
o $_POST
.
Manuel PHP : php://input
php://input est un flux en lecture seule qui vous permet de lire les données brutes à partir du corps de la demande ...php://input est non disponible avec enctype="multipart/form-data".
Les frameworks PHP à la rescousse ?
Les frameworks PHP comme Codeigniter 4 et Laravel utilisent une façade pour fournir une interface plus propre ( IncomingRequest
o Request
objets) à ce qui précède. C'est pourquoi les développeurs PHP professionnels utilisent des frameworks plutôt que du PHP brut.
Bien sûr, si vous aimez programmer, vous pouvez concevoir votre propre objet de façade pour fournir ce que font les frameworks. C'est parce que j'ai pris le temps d'étudier cette question que je suis en mesure d'écrire cette réponse.
L'encodage des URL ? Mais qu'est-ce que c'est que ça ?
En règle générale, si vous effectuez des requêtes HTTP normales et synchrones (lorsque la page entière est redessinée) avec un formulaire HTML, l'agent utilisateur (navigateur Web) codera les données du formulaire pour vous. Si vous souhaitez effectuer des requêtes HTTP asynchrones en utilisant la fonction XmlHttpRequest
vous devez alors façonner une chaîne de caractères urlencodée et l'envoyer, _si vous voulez que ces données apparaissent dans la base de données de l'UE. $_POST
superglobal_ .
Quel est votre niveau de connaissance de JavaScript ? :-)
La conversion d'un tableau ou d'un objet JavaScript en une chaîne de caractères urlencodée dérange de nombreux développeurs (même avec les nouvelles API telles que Données du formulaire ). Ils préfèrent de loin pouvoir simplement envoyer du JSON, et ce serait plus efficace pour le code client de le faire.
Rappelez-vous (clin d'œil, clin d'œil), le développeur web moyen n'apprend pas à utiliser l'outil de gestion de l'information. XmlHttpRequest
directement des objets, des fonctions globales, des fonctions de chaîne, des fonctions de tableau et des expressions régulières comme vous et moi ;-). L'urlencodage pour eux est un cauchemar ;-)
PHP, que se passe-t-il ?
L'absence de gestion intuitive de XML et JSON en PHP rebute beaucoup de personnes. On aurait pu penser que cela ferait partie de PHP depuis le temps (soupir).
Tant de types de médias (types MIME dans le passé)
Les formats XML, JSON et YAML ont tous des types de médias qui peuvent être intégrés dans un protocole HTTP. Content-Type
en-tête.
- application/xml
- applicaiton/json
- application/yaml (bien que l'IANA ne dispose d'aucune désignation officielle)
Regardez combien de types de médias (anciennement, les types MIME) sont définis par l'IANA.
Regardez combien de En-têtes HTTP il y en a.
php://input or bust
Utilisation de la php://input
stream vous permet de contourner le niveau d'abstraction de baby-sitting / hand holding que PHP a imposé au monde :-) De grands pouvoirs impliquent de grandes responsabilités !
Maintenant, avant de traiter les valeurs de données transmises en continu par php://input
vous devez faire certaines choses.
- Déterminez si le bon Méthode HTTP a été indiqué (GET, POST, PUT, PATCH, DELETE, ...)
- Déterminez si le HTTP Content-Type a été transmis.
- Déterminer si le valeur pour le Content-Type est le média souhaité souhaité.
- Déterminer si les données envoyées sont bien formé XML / JSON / YAML etc.
- Si nécessaire, convertir les données vers un type de données PHP : tableau ou objet.
-
Si l'une de ces vérifications ou conversions de base échoue, une exception est levée. !
Qu'en est-il du codage des caractères ?
AH, HA ! Oui, vous pouvez souhaiter que le flux de données envoyé à votre application soit encodé en UTF-8, mais comment savoir s'il l'est ou non ?
Deux problèmes critiques.
- Vous ne savez pas combien de données passent par le système.
php://input
.
- Vous ne connaissez pas avec certitude l'encodage actuel du flux de données.
Allez-vous tenter de manipuler des données de flux sans savoir d'abord combien il y en a ? C'est une idée terrible . Vous ne pouvez pas compter exclusivement sur le HTTP Content-Length
pour obtenir des indications sur la taille de l'entrée en continu, car elle peut être falsifiée.
Vous allez avoir besoin d'un :
- Algorithme de détection de la taille du flux.
- Limites de taille de flux définies par l'application (les limites d'Apache / Nginx / PHP peuvent être trop larges).
Allez-vous tenter de convertir les données du flux en UTF-8 sans connaître l'encodage actuel du flux ? Comment ? Le filtre de flux iconv ( exemple de filtre de flux iconv ) semble vouloir un encodage de début et de fin, comme ceci.
'convert.iconv.ISO-8859-1/UTF-8'
Ainsi, si vous êtes consciencieux, vous en aurez besoin :
- Algorithme de détection du codage du flux.
- Algorithme de définition de filtre de flux dynamique / runtime (car on ne peut pas connaître le codage de départ a priori).
( Mise à jour : 'convert.iconv.UTF-8/UTF-8'
forcera tout à UTF-8, mais vous devez toujours tenir compte des caractères que la bibliothèque iconv pourrait ne pas savoir comment traduire. En d'autres termes, vous devez définir d'une manière ou d'une autre l'action à entreprendre lorsqu'un caractère ne peut pas être traduit : 1) Insérer un caractère factice, 2) Échouer / lancer une exception).
Vous ne pouvez pas compter exclusivement sur le HTTP Content-Encoding
car cela pourrait indiquer quelque chose comme une compression comme dans le cas suivant. Ce n'est pas sur cette base que vous devez prendre une décision en ce qui concerne iconv.
Content-Encoding: gzip
Par conséquent, les étapes générales pourraient être ...
Partie I : Requêtes HTTP liées
- Déterminez si le bon Méthode HTTP a été indiqué (GET, POST, PUT, PATCH, DELETE, ...)
- Déterminez si le HTTP Content-Type a été transmis.
- Déterminer si le valeur pour le Content-Type est le média souhaité souhaité.
Partie II : Données de flux liées
- Déterminer la taille du flux d'entrée (facultatif, mais recommandé).
- Déterminer l'encodage du flux d'entrée.
- Si nécessaire, convertissez le flux d'entrée dans le caractère souhaité. caractères (UTF-8).
- Si nécessaire, annulez toute compression ou tout cryptage au niveau de l'application, puis répétez les étapes 4, 5 et 6.
Partie III : Type de données
- Déterminer si les données envoyées sont bien formé XML / JSON / YMAL etc.
(N'oubliez pas que les données peuvent toujours être une chaîne codée en URL que vous devez ensuite analyser et décoder en URL).
- Si nécessaire, convertir les données vers un type de données PHP : tableau ou objet.
Partie IV : La valeur des données
-
Filtrer les données d'entrée.
-
Valider les données d'entrée.
Vous voyez maintenant ?
Le site $_POST
superglobal, ainsi que les paramètres php.ini pour les limites de saisie, sont plus simples pour le profane. Cependant, le traitement de l'encodage des caractères est beaucoup plus intuitif et efficace lorsqu'on utilise des flux, car il n'est pas nécessaire de boucler à travers les superglobales (ou les tableaux, en général) pour vérifier le bon encodage des valeurs d'entrée.
5 votes
J'avais l'habitude d'utiliser des "hacks" pour recevoir des appels ajax du côté PHP avant de tomber sur cet article et de lire ses réponses géniales ! Pour les autres personnes ayant le même problème à l'avenir, j'espère que les moteurs de recherche liront aussi mon commentaire ! :)
0 votes
Vous n'auriez besoin d'utiliser php://input que si votre requête AJAX jQuery envoyait du JSON, au lieu de paires clé/valeur codées par URL. Par défaut, c'est ce que fait jQuery. Si c'est le cas (vos données sont en JSON), alors oui, vous devez utiliser
php://input
.