Umgang mit PUT / DELETE-Argumenten in PHP

84

Ich arbeite an meiner REST-Client-Bibliothek für CodeIgniter und habe Probleme damit, herauszufinden, wie PUT- und DELETE-Argumente in PHP gesendet werden.

An einigen Stellen habe ich Leute gesehen, die die Optionen verwendet haben:

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

Ärgerlicherweise scheint dies nichts zu bewirken. Ist dies der richtige Weg, um PUT-Parameter einzustellen?

Wenn ja, wie stelle ich die DELETE-Parameter ein?

$ this-> option () ist Teil meiner Bibliothek. Es baut einfach ein Array von CURLOPT_XX-Konstanten auf und sendet sie an curl_setopt_array (), wenn die aufgebaute cURL-Anforderung ausgeführt wird.

Ich versuche, die Parameter PUT und DELETE mit dem folgenden Code zu lesen:

        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;

Hier gibt es zwei Möglichkeiten: Ich gehe das falsch an oder irgendwo in meinen Bibliotheken gibt es einen Fehler. Wenn Sie mich wissen lassen könnten, ob dies theoretisch funktionieren sollte, kann ich das Debuggen einfach so lange durchschlagen, bis ich es gelöst habe.

Ich möchte keine Zeit mehr mit einem Ansatz verschwenden, der grundlegend falsch ist.

Phil Sturgeon
quelle
PUT funktioniert einwandfrei, nur DELETE-Parameter, um sich jetzt Gedanken über die Einstellung zu machen.
Phil Sturgeon
1
Diese Frage ist verwirrend. Geht es um Senden POST / DELETEParameter oder Empfangen POST / DELETEParameter?
Jameshfisher

Antworten:

68

Anstatt use zu CURLOPT_PUT = TRUEverwenden CURLOPT_CUSTOMREQUEST = 'PUT' und CURLOPT_CUSTOMREQUEST = 'DELETE'dann einfach Werte mit zu setzen CURLOPT_POSTFIELDS.

Phil Sturgeon
quelle
Wie erhalte ich POSTFIELDS auf der API / Server-Seite?
Daniel
48

Hier ist ein Code, der für andere hilfreich sein kann, die PUT- und DELETE-Parameter verarbeiten möchten. Sie können festlegen $_PUTund $_DELETEüber $GLOBALS[], aber sie sind in Funktionen nur dann direkt verfügbar, wenn sie deklariert sind globaloder über$GLOBALS[] . Um dies zu umgehen, habe ich eine einfache Klasse zum Lesen von GET / POST / PUT / DELETE-Anforderungsargumenten erstellt. Dies wird auch $_REQUESTmit PUT / DELETE-Parametern gefüllt.

Diese Klasse analysiert die PUT / DELETE-Parameter und unterstützt auch 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
quelle
16

Denken Sie daran, dass die meisten Webserver keine PUT & DELETE-Anforderungen verarbeiten. Da Sie eine Bibliothek erstellen, würde ich vorschlagen, darüber nachzudenken, dies zu berücksichtigen. Normalerweise gibt es zwei Konventionen, mit denen Sie PUT & DELETE per POST nachahmen können.

  1. Verwenden Sie eine benutzerdefinierte POST-Variable (z. B. _METHOD = PUT), die POST überschreibt
  2. Legen Sie einen benutzerdefinierten HTTP-Header fest (z. B. X-HTTP-Method-Override: PUT).

Im Allgemeinen unterstützen die meisten RESTful-Services, die PUT & DELETE nicht direkt zulassen, mindestens eine dieser Strategien. Mit cURL können Sie bei Bedarf über die CURLOPT_HTTPHEADEROption einen benutzerdefinierten Header festlegen .

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

Ich denke, Sie mischen Ihre Verben - PUT dient zum Einfügen einer Datei, POST zum Posten von Variablen (obwohl Sie eine Datei POSTEN können).

Verwenden Sie zum Festlegen der Post-Variablen CURLOPT_POSTFIELDSentweder eine Zeichenfolge param1=val1&param2=val2oder ein assoziatives Array.

Um ein LÖSCHEN durchzuführen, sollten Sie die Curl-Option verwenden CURLOPT_CUSTOMREQUEST

Adam Hopkinson
quelle
1
PUT und DELETE unterstützen beide das Senden zusätzlicher Argumente. Sie können dies über die Befehlszeile tun, wenn Sie mit Curl arbeiten, aber ich kann nicht herausfinden, wie man mit PHP-cURL sendet. Da dies beispielsweise für REST gilt, muss ich markieren, was ich lösche. Wenn ich die Benutzer-ID lösche, möchte ich die ID übergeben können, ohne die URL zu überladen. APIs wie Twitter unterstützen nur GET / POST, sodass Sie dies in die URL einfügen können. Andere REST-APIs unterstützen diese Art von Dingen jedoch möglicherweise nicht. Daher muss ich einen Löschparameter dafür senden.
Phil Sturgeon
1
Ok, ich habe PUT-Parameter, ich habe CURLOPT_PUT = TRUE gegen CURLOPT_CUSTOMREQUEST = 'PUT' getauscht und das funktioniert einwandfrei. Wie zum Teufel stelle ich DELETE ein?
Phil Sturgeon
CURLOPT_CUSTOMREQUEST = 'DELETE', dann Abfragezeichenfolge für die Parameter verwenden
Adam Hopkinson
1
Zum Schluss habe ich versucht, sie nicht in der Abfragezeichenfolge zu verwenden, wie ich bereits erwähnt habe. Es stellt sich heraus, dass Sie CURLOPT_POSTFIELDS mit PUT und DELETE verwenden können, wenn Sie CURLOPT_CUSTOMREQUEST = 'DELETE verwenden. Vielen Dank für Ihr Feedback, aber ich habe es am Ende selbst gelöst :-)
Phil Sturgeon
2
Hast du? Ich habe damals überhaupt nicht geholfen?
Adam Hopkinson
2

Dies ist meine Version von DELETE for CI. Es akzeptiert Argumente im GET-Stil für DELETE, auch Argumente mit demselben Namen, dh: 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
quelle
1

So löse ich mein DELETE-Problem:

== >> in REST_Controller.php ersetze ich die delault _parse_delete () Funktion durch:

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

;) Für mich geht das!

okobsamoht
quelle
1
$ _DELETE;? Ich bekomme nur Fehler undefinierte Variable: _DELETE
Valor_