Gestire argomenti PUT / DELETE in PHP


84

Sto lavorando alla mia libreria client REST per CodeIgniter e sto lottando per capire come inviare argomenti PUT e DELETE in PHP.

In alcuni posti ho visto persone che utilizzano le opzioni:

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

Fastidiosamente, questo sembra non fare nulla. È questo il modo corretto per impostare i parametri PUT?

In tal caso, come imposto i parametri DELETE?

$ this-> option () fa parte della mia libreria, crea semplicemente un array di costanti CURLOPT_XX e le invia a curl_setopt_array () quando viene eseguita la richiesta cURL compilata.

Sto tentando di leggere i parametri PUT e DELETE utilizzando il seguente codice:

        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;

Ci sono due opzioni qui, mi sto avvicinando a questo nel modo sbagliato o c'è un bug da qualche parte nelle mie librerie. Se potessi farmi sapere se questo dovrebbe teoricamente funzionare, posso semplicemente martellare il debug fino a quando non lo risolvo.

Non voglio sprecare altro tempo su un approccio che è fondamentalmente sbagliato.


PUT funziona bene, elimina i parametri per preoccuparti di impostarli ora.
Phil Sturgeon

1
Questa domanda è fonte di confusione. Si tratta di inviare POST / DELETEparametri o ricevere POST / DELETEparametri?
jameshfisher

Risposte:


68

Invece di usare CURLOPT_PUT = TRUEuse CURLOPT_CUSTOMREQUEST = 'PUT' e CURLOPT_CUSTOMREQUEST = 'DELETE'quindi impostare i valori con CURLOPT_POSTFIELDS.


Come ricevo i POSTFIELDS dal lato API / server?
Daniel

48

Ecco del codice che può essere utile per gli altri che desiderano gestire i parametri PUT e DELETE. È possibile impostare $_PUTe $_DELETEtramite $GLOBALS[], ma non saranno direttamente accessibili nelle funzioni a meno che non siano dichiarati globalo accessibili tramite $GLOBALS[]. Per aggirare questo problema, ho creato una semplice classe per leggere gli argomenti della richiesta GET / POST / PUT / DELETE. Questo viene popolato anche $_REQUESTcon i parametri PUT / DELETE.

Questa classe analizzerà i parametri PUT / DELETE e supporterà anche 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;
    }
  }
}

16

Ricorda, la maggior parte dei server web non gestisce le richieste PUT & DELETE. Dato che stai realizzando una libreria, ti suggerirei di pensare a come tenerne conto. In genere, ci sono due convenzioni che puoi usare per imitare PUT & DELETE tramite POST.

  1. usa una variabile POST personalizzata (es. _METHOD = PUT) che sostituisce POST
  2. impostare un'intestazione HTTP personalizzata (es. X-HTTP-Method-Override: PUT)

In generale, la maggior parte dei servizi RESTful che non consentono PUT & DELETE direttamente supporteranno almeno una di queste strategie. Puoi usare cURL per impostare un'intestazione personalizzata se necessario tramite l' CURLOPT_HTTPHEADERopzione.

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

3

Penso che tu stia mescolando i tuoi verbi - PUT è per mettere un file, POST è per pubblicare variabili (anche se puoi POST un file).

Per impostare le variabili post, utilizzare CURLOPT_POSTFIELDScon una stringa di param1=val1&param2=val2o un array associativo.

Per eseguire un DELETE, ti consigliamo di utilizzare l'opzione curl CURLOPT_CUSTOMREQUEST


1
PUT e DELETE supportano entrambi l'invio di argomenti aggiuntivi. Puoi farlo tramite la riga di comando quando lavori con curl ma non riesco a capire come inviare con PHP-cURL. Ad esempio, poiché questo è per REST, ho bisogno di un modo per contrassegnare ciò che sto eliminando. Se elimino l'ID utente, voglio essere in grado di passare l'ID senza ingombrare l'URL. API come Twitter supportano solo GET / POST in modo da poterlo inserire nell'URL, ma altre API REST potrebbero non supportare questo genere di cose, quindi ho bisogno di inviare un parametro di cancellazione per questo.
Phil Sturgeon

1
Ok, ho i parametri PUT funzionanti, ho scambiato CURLOPT_PUT = TRUE per CURLOPT_CUSTOMREQUEST = 'PUT' e funziona bene. Ora, come diavolo imposto DELETE?
Phil Sturgeon

CURLOPT_CUSTOMREQUEST = 'DELETE', quindi utilizzare la stringa di query per i parametri forse
Adam Hopkinson

1
Chiudi, stavo cercando di evitare di usarli nella stringa di query come ho già menzionato. Risulta che puoi usare CURLOPT_POSTFIELDS con PUT e DELETE quando usi CURLOPT_CUSTOMREQUEST = 'DELETE. Grazie per il tuo feedback, ma alla fine l'ho risolto io stesso :-)
Phil Sturgeon

2
Hai fatto? Allora non ho aiutato per niente?
Adam Hopkinson

2

Questa è la mia versione di DELETE per CI. Accetta argomenti in stile GET per DELETE, anche argomenti con lo stesso nome, ad esempio: 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

Ecco come risolvo il mio problema di CANCELLAZIONE:

== >> in REST_Controller.php sostituisco la funzione delault _parse_delete () con:

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);
}

;) per me funziona!


1
$ _DELETE ;? Ricevo solo errore variabile non definita: _DELETE
Valor_
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.