Обработка аргументов PUT / DELETE в PHP

84

Я работаю над своей клиентской библиотекой 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;

Здесь есть два варианта: я неправильно подхожу к этому или где-то в моих библиотеках есть ошибка. Если бы вы могли сообщить мне, должно ли это теоретически сработать, я могу просто продолжить отладку, пока не решу ее.

Я не хочу больше тратить время на принципиально неправильный подход.

Фил Стерджен
источник
PUT работает нормально, просто УДАЛИТЕ параметры, чтобы беспокоиться о настройке сейчас.
Фил Стерджен
1
Этот вопрос сбивает с толку. Это об отправке POST / DELETEпараметрах или получении POST / DELETEпараметрах?
jameshfisher

Ответы:

68

Вместо использования CURLOPT_PUT = TRUEиспользуйте, CURLOPT_CUSTOMREQUEST = 'PUT' а CURLOPT_CUSTOMREQUEST = 'DELETE'затем просто установите значения с помощью CURLOPT_POSTFIELDS.

Фил Стерджен
источник
Как получить ПОЧТОВЫЕ ПОЛЯ на стороне api / сервера?
Daniel
48

Вот код, который может быть полезен для других, желающих обрабатывать параметры PUT и DELETE. Вы можете установить $_PUTи $_DELETEчерез $GLOBALS[], но они не будут напрямую доступны в функциях, если они не объявлены globalили не доступны через $GLOBALS[]. Чтобы обойти это, я создал простой класс для чтения аргументов запроса GET / POST / PUT / DELETE. Это также заполняется параметрами $_REQUESTPUT / 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;
    }
  }
}
Брайан Дрюери
источник
16

Просто помните, что большинство веб-серверов не обрабатывают запросы PUT & DELETE. Поскольку вы делаете библиотеку, я бы посоветовал подумать об учете этого. Как правило, есть два соглашения, которые можно использовать для имитации PUT и DELETE через POST.

  1. используйте пользовательскую переменную POST (например, _METHOD = PUT), которая переопределяет POST
  2. установить собственный HTTP-заголовок (например, X-HTTP-Method-Override: PUT)

Вообще говоря, большинство служб RESTful, которые не позволяют напрямую PUT & DELETE, будут поддерживать по крайней мере одну из этих стратегий. Вы можете использовать cURL для установки собственного заголовка, если вам нужно с помощью CURLOPT_HTTPHEADERопции.

// ex...
curl_setopt($ch, CURLOPT_HTTPHEADER, array('X-HTTP-Method-Override: PUT') );
Оуэн
источник
3

Я думаю, вы смешиваете свои глаголы - PUT для размещения файла, POST для публикации переменных (хотя вы можете POST файл).

Чтобы установить переменные сообщения, используйте CURLOPT_POSTFIELDSлибо строку, param1=val1&param2=val2либо ассоциативный массив.

Чтобы выполнить DELETE, вы захотите использовать параметр curl CURLOPT_CUSTOMREQUEST

Адам Хопкинсон
источник
1
PUT и DELETE поддерживают отправку дополнительных аргументов. Вы можете сделать это через командную строку при работе с curl, но я не могу понять, как отправить с PHP-cURL. Например, поскольку это для REST, мне нужен способ отметить, что я удаляю. Если я удаляю идентификатор пользователя, я хочу иметь возможность передавать идентификатор, не загромождая URL-адрес. API, такие как Twitter, поддерживают только GET / POST, поэтому вы можете поместить это в URL-адрес, но другие API REST могут не поддерживать такого рода вещи, поэтому мне нужно отправить для него параметр удаления.
Фил Стерджен
1
Хорошо, у меня работают параметры PUT, я заменил CURLOPT_PUT = TRUE на CURLOPT_CUSTOMREQUEST = 'PUT', и все работает нормально. Как, черт возьми, мне установить DELETE?
Фил Стерджен
CURLOPT_CUSTOMREQUEST = 'DELETE', затем использовать строку запроса для параметров, возможно,
Адам Хопкинсон
1
Близко, я пытался избежать их использования в строке запроса, как я уже упоминал. Оказывается, вы можете использовать CURLOPT_POSTFIELDS с PUT и DELETE при использовании CURLOPT_CUSTOMREQUEST = 'DELETE. Спасибо за отзыв, но в конце концов я решил это сам :-)
Фил Стерджен
2
А ты? Я тогда совсем не помог?
Адам Хопкинсон
2

Это моя версия 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;
            }
        }
    }
}
Патрик Саваль
источник
1

Вот как я решил проблему с УДАЛЕНИЕМ:

== >> в REST_Controller.php я заменяю функцию delault _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);
}

;) меня устраивает!

окобсамохт
источник
1
$ _DELETE ;? Я просто получаю сообщение об ошибке undefined variable: _DELETE
Valor_