web-dev-qa-db-fra.com

La demande PATCH et PUT ne fonctionne pas avec les données de formulaire

J'utilise Laravel pour créer une application RESTFUL et je teste l'application avec Postman. Actuellement, il y a un problème pour PATCH ou PUT si les données envoyées de Postman avec form-data.

// Parameter `{testimonial}` will be sent to backend.
Route::post  ('testimonials/{testimonial}', 'TestimonialController@update');

// Parameter `{testimonial}` will not be sent to backend (`$request->all()` will be empty) if sent from Postman with form-data.
Route::patch ('testimonials/{testimonial}', 'TestimonialController@update');
Route::put   ('testimonials/{testimonial}', 'TestimonialController@update');
  • En utilisant les données de formulaire, $request->all() conviendra à POST.
  • En utilisant x-www-form-urlencoded, $request->all() conviendra pour PATCH, PUT et POST.
  • Cependant, si j'envoie PUT et PATCH avec des données de formulaire de Postman, la $request->all() sera vide (les paramètres ne seront pas envoyés au backend).

À l'heure actuelle, la solution consiste à utiliser POST pour mettre à jour un modèle. Je veux savoir pourquoi PATCH et PUT ne fonctionne pas lorsqu'ils sont envoyés avec des données de formulaire de Postman.

9
notalentgeek

Il s'agit d'un problème connu et la solution de contournement selon le Github suivant commentaire est que lors de l'envoi d'une demande PATCH/PUT, vous devez procéder comme suit:

Vous devez envoyer POST et définir _method sur PUT (identique à l'envoi de formulaires) pour rendre vos fichiers visibles

Donc, essentiellement, vous envoyez une demande POST avec un paramètre qui définit la méthode réelle et Laravel semble comprendre cela.

Selon le documentation :

Étant donné que les formulaires HTML ne peuvent pas effectuer de demandes PUT, PATCH ou DELETE, vous devrez ajouter un champ caché _method Pour usurper ces verbes HTTP. La directive @method Blade peut créer ce champ pour vous:

<form action="/foo/bar" method="POST">
    @method('PUT')

    ...
</form> 

Vous pouvez également utiliser la fonction d'assistance method_field pour effectuer les opérations ci-dessus:

La fonction method_field génère un champ de saisie HTML caché contenant la valeur usurpée du verbe HTTP du formulaire. Par exemple, en utilisant la syntaxe Blade:

<form method="POST">
    {{ method_field('PUT') }}
</form>
15
Script47

La méthode Laravel PATCH et PUT ne fonctionne pas avec form-data, C'est un problème connu de Symfony et même PHP (Google pour cela - Laravel utilise plusieurs Les packages de la fondation Symfony, incluent Request).

  1. Si vous n'avez pas besoin de transmettre des fichiers via une demande, remplacez form-data Par raw avec le type de contenu json. Par exemple: {"name":"changed"}. Il sera lu comme php://input Et votre code devrait bien fonctionner ($request->all() est maintenant ["name" => "changed]).

  2. Si vous avez besoin de passer des fichiers, à mon avis, NE PAS passez-le dans les méthodes API REST. Vous pouvez écrire une autre méthode pour faire tout ce dont vous avez besoin avec votre fichier (par exemple: POST form-data -> télécharger le fichier -> mettre à jour la base de données -> renvoyer un chemin de fichier/url/même son contenu base64), alors vous pouvez utiliser sa sortie/résultat pour continuer votre méthode patch/put (raw avec le type de contenu json). Je le fais toujours lorsque je travaille avec des fichiers dans l'API.

J'espère que cette aide!

2
vietanhyt

Les types de supports de formulaire n'ont pas de sémantique définie pour PATCH, c'est donc vraiment une mauvaise idée de les utiliser (voir https://www.rfc-editor.org/errata/eid3169 ).

Pour PUT, le comportement attendu serait de stocker uniquement la charge utile codée par formulaire (dans ce format). Est-ce vraiment ce que tu veux ici?

1
Julian Reschke