web-dev-qa-db-fra.com

Gestion des arguments PUT / DELETE dans PHP

Je travaille sur ma bibliothèque cliente REST pour CodeIgniter et j'ai du mal à trouver comment envoyer les 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);

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

Si oui, 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 en utilisant le 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 cette question de la mauvaise façon ou il y a un bug 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 pas perdre plus de temps sur une approche qui est fondamentalement erronée.

83
Phil Sturgeon

À la place d'utiliser CURLOPT_PUT = TRUE utilisation CURLOPT_CUSTOMREQUEST = 'PUT' et CURLOPT_CUSTOMREQUEST = 'DELETE' puis définissez simplement les valeurs avec CURLOPT_POSTFIELDS.

68
Phil Sturgeon

Voici du code qui peut être utile pour ceux qui souhaitent gérer les paramètres PUT et DELETE. Vous pouvez définir $_PUT et $_DELETE via $GLOBALS[], mais ils ne seront pas directement accessibles dans les fonctions sauf s'ils sont déclarés global ou accessibles via $GLOBALS[]. Pour contourner ce problème, j'ai créé une classe simple pour lire les arguments de requête GET/POST/PUT/DELETE. Cela remplit également $_REQUEST avec les paramè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;
    }
  }
}
48
Bryan Drewery

N'oubliez pas que la plupart des serveurs Web ne traitent pas les demandes 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 le CURLOPT_HTTPHEADER option.

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

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

Pour définir les variables de publication, utilisez CURLOPT_POSTFIELDS avec soit une chaîne de param1=val1&param2=val2 ou un tableau associatif.

Pour effectuer une suppression, vous devez utiliser l'option curl CURLOPT_CUSTOMREQUEST

3
Adam Hopkinson

Voici comment je résous mon problème DELETE:

== >> dans REST_Controller.php je remplace la fonction par défaut _ 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!

1
okobsamoht

Ceci est ma version de DELETE for CI. Il accepte les arguments de style GET pour la suppression, même les arguments du 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;
            }
        }
    }
}
1
Patrick Savalle