Ответ 1
Вместо использования CURLOPT_PUT = TRUE
используйте CURLOPT_CUSTOMREQUEST = 'PUT'
и CURLOPT_CUSTOMREQUEST = 'DELETE'
, то просто установите значения с помощью CURLOPT_POSTFIELDS
.
Я работаю над своей клиентской библиотекой REST для CodeIgniter, и я изо всех сил пытаюсь разобраться, как отправлять аргументы PUT и DELETE в PHP.
В нескольких местах я видел людей, использующих параметры:
$this->option(CURLOPT_PUT, TRUE);
$this->option(CURLOPT_POSTFIELDS, $params);
Раздражающе, это, кажется, ничего не делает. Правильно ли это установить параметры PUT?
Если да, как установить параметры DELETE?
$this- > option() является частью моей библиотеки, она просто создает массив констант CURLOPT_XX и отправляет их curl_setopt_array() при выполнении запрошенного запроса cURL.
Я пытаюсь читать параметры PUT и DELETE, используя следующий код:
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;
Здесь есть два варианта: я приближаюсь к этому неправильно, или есть ошибка где-то в моих библиотеках. Если бы вы могли сообщить мне, если это теоретически будет работать, я могу просто отложить отладку до тех пор, пока не решит проблему.
Я не хочу тратить больше времени на подход, который в корне неверен.
Вместо использования CURLOPT_PUT = TRUE
используйте CURLOPT_CUSTOMREQUEST = 'PUT'
и CURLOPT_CUSTOMREQUEST = 'DELETE'
, то просто установите значения с помощью CURLOPT_POSTFIELDS
.
Вот код, который может быть полезен для других, которые хотят обрабатывать параметры PUT и DELETE. Вы можете установить $_PUT
и $_DELETE
через $GLOBALS[]
, но они не будут напрямую доступны в функциях, если не объявлены global
или доступны через $GLOBALS[]
. Чтобы обойти это, я сделал простой класс для чтения аргументов запроса GET/POST/PUT/DELETE. Это также заполняет $_REQUEST
параметрами PUT/DELETE.
Этот класс будет анализировать параметры PUT/DELETE и поддерживать 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;
}
}
}
Просто помните, что большинство веб-серверов не обрабатывают запросы PUT и DELETE. Поскольку вы создаете библиотеку, я бы предложил подумать об учете этого. Как правило, существуют два соглашения, которые вы можете использовать для имитации PUT и DELETE через POST.
В целом, большинство служб RESTful, которые не позволяют PUT и DELETE напрямую поддерживать хотя бы одну из этих стратегий. Вы можете использовать cURL для установки настраиваемого заголовка, если вам нужна опция CURLOPT_HTTPHEADER
.
// ex...
curl_setopt($ch, CURLOPT_HTTPHEADER, array('X-HTTP-Method-Override: PUT') );
Я думаю, что вы смешиваете свои глаголы - PUT предназначен для размещения файла, POST - для публикации переменных (хотя вы можете POST файл).
Чтобы установить пост-переменные, используйте CURLOPT_POSTFIELDS
либо с строкой param1=val1¶m2=val2
, либо с помощью ассоциативного массива.
Чтобы выполнить DELETE, вы хотите использовать параметр curl CURLOPT_CUSTOMREQUEST
Вот как я единственная моя проблема DELETE:
== → в REST_Controller.php я заменяю функцию _parse_delete() делом на:
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);
}
;) он работает для меня!
Это моя версия DELETE для CI. Он принимает аргументы GET-стиля для DELETE, даже те же имена, например: 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;
}
}
}
}