Gestion des arguments PUT / DELETE en PHP

84

Je travaille sur ma bibliothèque cliente REST pour CodeIgniter et j'ai du mal à comprendre comment envoyer des arguments PUT et DELETE en PHP.

Dans quelques endroits, j'ai vu des gens utiliser les options:

$this->option(CURLOPT_PUT, TRUE);
$this->option(CURLOPT_POSTFIELDS, $params);

Malheureusement, cela semble ne rien faire. Est-ce la bonne façon de définir les paramètres PUT?

Si tel est le cas, comment définir les paramètres DELETE?

$ this-> option () fait partie de ma bibliothèque, il construit simplement un tableau de constantes CURLOPT_XX et les envoie à curl_setopt_array () lorsque la requête cURL construite est exécutée.

J'essaie de lire les paramètres PUT et DELETE à l'aide du code suivant:

        case 'put':
            // Set up out PUT variables
            parse_str(file_get_contents('php://input'), $this->_put_args);
        break;

        case 'delete':
            // Set up out PUT variables
            parse_str(file_get_contents('php://input'), $this->_delete_args);
        break;

Il y a deux options ici, j'aborde cela de la mauvaise manière ou il y a un bogue quelque part dans mes bibliothèques. Si vous pouviez me faire savoir si cela devrait théoriquement fonctionner, je peux simplement marteler le débogage jusqu'à ce que je le résolve.

Je ne veux plus perdre de temps avec une approche fondamentalement erronée.

Phil Sturgeon
la source
PUT fonctionne correctement, il suffit de SUPPRIMER les paramètres pour vous soucier du réglage maintenant.
Phil Sturgeon
1
Cette question prête à confusion. S'agit-il d' envoi POST / DELETEparamètres ou de réception POST / DELETEparamètres?
jameshfisher

Réponses:

68

Au lieu d'utiliser CURLOPT_PUT = TRUEuse CURLOPT_CUSTOMREQUEST = 'PUT' , CURLOPT_CUSTOMREQUEST = 'DELETE'puis définissez simplement des valeurs avec CURLOPT_POSTFIELDS.

Phil Sturgeon
la source
Comment recevoir POSTFIELDS côté API / serveur?
Daniel le
48

Voici un code qui peut être utile pour les autres souhaitant gérer les paramètres PUT et DELETE. Vous pouvez définir $_PUTet $_DELETEvia $GLOBALS[], mais ils ne seront pas directement accessibles dans les fonctions à moins d'être déclarés globalou accessibles via $GLOBALS[]. Pour contourner cela, j'ai créé une classe simple pour lire les arguments de requête GET / POST / PUT / DELETE. Cela remplit également les $_REQUESTparamètres PUT / DELETE.

Cette classe analysera les paramètres PUT / DELETE et prendra également en charge GET / POST.

class Params {
  private $params = Array();

  public function __construct() {
    $this->_parseParams();
  }

  /**
    * @brief Lookup request params
    * @param string $name Name of the argument to lookup
    * @param mixed $default Default value to return if argument is missing
    * @returns The value from the GET/POST/PUT/DELETE value, or $default if not set
    */
  public function get($name, $default = null) {
    if (isset($this->params[$name])) {
      return $this->params[$name];
    } else {
      return $default;
    }
  }

  private function _parseParams() {
    $method = $_SERVER['REQUEST_METHOD'];
    if ($method == "PUT" || $method == "DELETE") {
        parse_str(file_get_contents('php://input'), $this->params);
        $GLOBALS["_{$method}"] = $this->params;
        // Add these request vars into _REQUEST, mimicing default behavior, PUT/DELETE will override existing COOKIE/GET vars
        $_REQUEST = $this->params + $_REQUEST;
    } else if ($method == "GET") {
        $this->params = $_GET;
    } else if ($method == "POST") {
        $this->params = $_POST;
    }
  }
}
Bryan Drewery
la source
16

N'oubliez pas que la plupart des serveurs Web ne gèrent pas les requêtes PUT & DELETE. Puisque vous créez une bibliothèque, je vous suggère de penser à en tenir compte. En règle générale, il existe deux conventions que vous pouvez utiliser pour imiter PUT & DELETE via POST.

  1. utiliser une variable POST personnalisée (ex. _METHOD = PUT) qui remplace POST
  2. définir un en-tête HTTP personnalisé (ex. X-HTTP-Method-Override: PUT)

De manière générale, la plupart des services RESTful qui n'autorisent pas directement PUT & DELETE prendront en charge au moins une de ces stratégies. Vous pouvez utiliser cURL pour définir un en-tête personnalisé si vous en avez besoin via l' CURLOPT_HTTPHEADERoption.

// ex...
curl_setopt($ch, CURLOPT_HTTPHEADER, array('X-HTTP-Method-Override: PUT') );
Owen
la source
3

Je pense que vous mélangez vos verbes - PUT est pour mettre un fichier, POST est pour poster des variables (bien que vous puissiez POSTER un fichier).

Pour définir les variables de publication, utilisez-les CURLOPT_POSTFIELDSavec une chaîne de param1=val1&param2=val2ou un tableau associatif.

Pour faire un DELETE, vous voudrez utiliser l'option curl CURLOPT_CUSTOMREQUEST

Adam Hopkinson
la source
1
PUT et DELETE prennent tous deux en charge l'envoi d'arguments supplémentaires. Vous pouvez le faire via la ligne de commande lorsque vous travaillez avec curl, mais je ne peux pas savoir comment envoyer avec PHP-cURL. Par exemple, comme c'est pour REST, j'ai besoin d'un moyen de marquer ce que je supprime. Si je supprime l'ID utilisateur, je veux pouvoir transmettre l'ID sans encombrer l'URL. Les API comme Twitter ne prennent en charge que GET / POST, vous pouvez donc le mettre dans l'URL, mais d'autres API REST peuvent ne pas prendre en charge ce genre de chose, je dois donc envoyer un paramètre de suppression pour cela.
Phil Sturgeon
1
Ok, j'ai les paramètres PUT qui fonctionnent, j'ai échangé CURLOPT_PUT = TRUE pour CURLOPT_CUSTOMREQUEST = 'PUT' et cela fonctionne bien. Maintenant, comment diable puis-je définir DELETE?
Phil Sturgeon
CURLOPT_CUSTOMREQUEST = 'DELETE', puis utilisez la chaîne de requête pour les paramètres peut
Adam Hopkinson
1
Fermer, j'essayais d'éviter de les utiliser dans la chaîne de requête comme je l'ai déjà mentionné. Il s'avère que vous pouvez utiliser CURLOPT_POSTFIELDS avec PUT et DELETE lorsque vous utilisez CURLOPT_CUSTOMREQUEST = 'DELETE. Merci pour vos commentaires, mais je l'ai résolu moi-même à la fin :-)
Phil Sturgeon
2
As tu? Je n'ai pas du tout aidé alors?
Adam Hopkinson
2

Ceci est ma version de DELETE for CI. Il accepte les arguments de style GET pour DELETE, même les arguments de même nom, c'est-à-dire: GET / some / url? Id = 1 & id = 2 & id = 3

protected function _parse_delete()
{
    $query = $_SERVER['QUERY_STRING'];
    if ( !empty( $query ) )
    {
        foreach( explode('&', $query ) as $param )
        {
            list($k, $v) = explode('=', $param);
            $k = urldecode($k);
            $v = urldecode($v);
            if ( isset( $this->_delete_args[$k] ) )
            {
                if ( is_scalar( $this->_delete_args[$k] ) )
                {
                    $this->_delete_args[$k] = array( $this->_delete_args[$k] );
                }
                $this->_delete_args[$k][] = $v ;
            }
            else
            {
                $this->_delete_args[$k] = $v;
            }
        }
    }
}
Patrick Savalle
la source
1

Voici comment résoudre mon problème DELETE:

== >> dans REST_Controller.php je remplace la fonction delault _parse_delete () par:

protected function _parse_delete()
{
    $this->_delete_args = $_DELETE;
    $this->request->format and $this->request->body = file_get_contents('php://input');
    // Set up out DELETE variables (which shouldn't really exist, but sssh!)
    parse_str(file_get_contents('php://input'), $this->_delete_args);
}

;) ça marche pour moi!

okobsamoht
la source
1
$ _DELETE ;? Je viens d'obtenir une erreur de variable non définie: _DELETE
Valor_