7.4. Объект запроса

7.4.1. Введение

Объект запроса - это простой "объект значений" (value object), который передается между Zend_Controller_Front, маршрутизатором, диспетчером и контроллерами. Он хранит в себе имена запрошенных модуля, контроллера, действия и необязательные параметры, а также остальную среду (переменные) запроса, будь это HTTP, CLI или PHP-GTK.

  • Доступ к имени модуля производится через getModuleName() и setModuleName().

  • Доступ к имени контроллера производится через getControllerName() и setControllerName().

  • Доступ к имени действия производится через getControllerName() и setControllerName().

  • Параметры, доступные через действие, являются ассоциативным массивом пар ключ/значение, который извлекается целиком через метод getParams() и устанавливается через метод setParams(). Его элементы можно извлекать и устанавливать по отдельности через те же методы getParam() и setParam() соответственно.

Методов, которые можно использовать в запросе, может быть больше, в зависимости от типа запроса. Например, используемый по умолчанию запрос Zend_Controller_Request_Http имеет методы для получения URI запроса, пути в нем, параметров $_GET и $_POST, и т.д.

Объект запроса передается фронт-контроллеру, либо инициализируется в начале процесса диспетчеризации до того, как будет произведена маршрутизация. Он передается всем объектам в цепочке диспетчеризации.

Кроме того, объект запроса очень полезен в тестировании. Разработчик может вручную установить переменные запроса, включая модуль, контроллер, действие, параметры, URI и т.д., и передать объект запроса фронт-контроллеру для проверки процесса выполнения приложения. Если комбинировать его с объектом ответа, то становится возможным тщательное и точное юнит-тестирование приложений MVC.

7.4.2. HTTP-запросы

7.4.2.1. Доступ к данным запроса

Zend_Controller_Request_Http инкапсулирует доступ к соответствующим значениям, таким, как имя и значение ключа для переменных контроллера и действия, и все дополнительные параметры, полученные из URI. Он также позволяет обращаться к значениям, содержащимся в суперглобальных массивах, как к своим открытым членам, и управляет текущими базовым URL и URI запроса. Суперглобальные значения не могут устанавливаться в объекте запроса, вместо этого используйте методы setParam/getParam для установки или получения пользовательских параметров.

[Замечание] Суперглобальные данные

Когда получаете доступ к суперглобальным данным через Zend_Controller_Request_Http как к публичным свойствам, то необходимо помнить, что имя свойства (ключ суперглобального массива) сопоставляются с суперглобальными массивами в определенной последовательности: 1. GET, 2. POST, 3. COOKIE, 4. SERVER, 5. ENV.

Отдельные значения из суперглобальных массивов можно также получить через открытые методы. Например, необработанное значение $_POST['user'] может быть получено через вызов метода getPost('user') объекта запроса. Эти методы включают в себя getQuery() для получения элементов массива $_GET и getHeader() для получения заголовков запроса.

[Замечание] Данные GET и POST

Будьте осторожны, когда извлекаете данные из объекта запроса, поскольку они совсем не фильтруются. Маршрутизатор и диспетчер производят проверку на допустимость и фильтрацию данных для использования в своих целях, но оставляют их нетронутыми в объекте запроса.

[Замечание] Извлечение Raw POST данных

Начиная с версии 1.5.0 вы можете также извлекать данные POST в том виде, в котором они присутствуют в теле запроса, используя метод getRawPost(). Этот метод возвращает false, если данные POST отсутствуют в теле запроса, иначе - все тело POST.

Этот метод в основном полезен для получения содержимого при разработке RESTful приложений.

Вы можете также устанавливать пользовательские параметры в объекте запроса, используя setParam(), и извлекать их после, используя getParam(). Маршрутизатор использует этот функционал для установки параметров, обнаруженных в URI запроса, в объекте запроса.

[Замечание] getParam() извлекает не только пользовательские параметры

getParam() извлекает значения из нескольких источников. В порядке следования эти источники включают в себя: установленные через метод setParam() пользовательские параметры, параметры GET, и, наконец, параметры POST. Помните об этом, когда извлекаете данные через этот метод.

Если вы хотите извлекать только те параметры, которые установили через setParam(), то используйте getUserParam().

Кроме этого, начиная с версии 1.5.0, вы можете ограничивать набор доступных для поиска источников параметров. setParamSources() позволяет указывать пустой массив или массив с одним или более значений, это могут быть'_GET' и '_POST' (по умолчанию оба разрешены). Через этот массив задается набор источников параметров, которым можно пользоваться для поиска. Если вы хотите ограничить доступ источником '_GET', то указывайте setParamSources(array('_GET')).

[Замечание] Причуды Apache

Если вы используете обработчик ошибок 404 веб-сервера Apache для передачи приходящих запросов фронт-контроллеру или используете флаг PT с правилами перезаписи, то нужный вам URI будет содержаться в $_SERVER['REDIRECT_URL'], а не в $_SERVER['REQUEST_URI']. Если вы используете такие установки и получаете неверную маршрутизацию, то должны использовать для своего объекта запроса класс Zend_Controller_Request_Apache404 вместо Zend_Controller_Request_Http, используемого по умолчанию.

<?php
require_once 'Zend/Controller/Request/Apache404.php';
$request = new Zend_Controller_Request_Apache404();
$front->setRequest($request);
                

Этот класс расширяет Zend_Controller_Request_Http и просто изменяет автоопределение URI запроса. Он может использоваться в качестве замены.

7.4.2.2. Базовый URL и поддиректории

Zend_Controller_Request_Http позволяет использовать Zend_Controller_Router_Rewrite в поддиректориях. Zend_Controller_Request_Http попытается автоматически определить ваш базовый URL и соответствующим образом установить его.

Например, если вы храните ваш index.php в поддиректории /projects/myapp/index.php веб-сервера, то базовый URL (основа перезаписи) должен быть установлен в /projects/myapp. Эта строка будет удаляться из начала пути до того, как будут производиться поиск соответствующего маршрута. Это освобождает от необходимости ее указания в начале каждого маршрута. Маршрут 'user/:username' будет соответствовать URI вида http://localhost/projects/myapp/user/martel и http://example.com/user/martel.

[Замечание] Определение URL чувствительно к регистру

Автоматическое определение базового URL чувствительно к регистру, поэтому убедитесь, что ваш URL соответствует имени поддиректории в файловой системе (даже на платформе Windows). Если не соответствует, то будет сгенерировано исключение.

Если базовый URL определяется некорректно, то вы можете заменить его своим базовым путем с помощью метода setBaseUrl(), который есть в классах Zend_Http_Request, Zend_Controller_Request_Http и Zend_Controller_Front. Легче всего установить его через Zend_Controller_Front, который в свою очередь установит его в объекте запроса. Пример установки своего базового URL:

<?php
/**
 * Обработка запроса со своим базовым URL через Zend_Controller_Front
 */
$router     = new Zend_Controller_Router_Rewrite();
$controller = Zend_Controller_Front::getInstance();
$controller->setControllerDirectory('./application/controllers')
           ->setRouter($router)
           ->setBaseUrl('/projects/myapp'); // установка базового URL!
$response   = $controller->dispatch();
            

7.4.2.3. Определение HTTP-метода запроса

getMethod() позволяет определить HTTP-метод текущего запроса. Кроме этого, есть набор методов, позволяющий проверить, использовался ли тот или иной HTTP-метод при произведении текущего запроса. Все они возвращают ответ булевого типа:

  • isGet()

  • isPost()

  • isPut()

  • isDelete()

  • isHead()

  • isOptions()

Эти методы могут использоваться в основном для создания т.н. RESTful-архитектуры.

7.4.2.4. Определение запросов AJAX

Zend_Controller_Request_Http имеет зачаточный метод для определения запросов AJAX: isXmlHttpRequest(). Этот метод проверяет наличие заголовка HTTP-запроса X-Requested-With со значением 'XMLHttpRequest'. Если он найден, то возвращается true.

На данный момент известно, что этот заголовок по умолчанию отправляется следующими JS-библиотеками:

  • Prototype/Scriptaculous (и библиотеки, производные от Prototype)

  • Yahoo! UI Library

  • jQuery

  • MochiKit

Большинство AJAX-библиотек позволяет отправлять произвольные заголовки HTTP-запросов. Если ваша библиотека не отправляет этот заголовок, то просто добавьте его в качестве заголовка ответа, чтобы быть уверенным в том, что метод isXmlHttpRequest() работает для вас.

7.4.3. Создание подклассов объекта запроса

Базовый класс запроса, используемый для всех объектов запроса, - абстрактный класс Zend_Controller_Request_Abstract. Он определяет следующие методы:

abstract class Zend_Controller_Request_Abstract
{
    /**
     * @return string
     */
    public function getControllerName();

    /**
     * @param string $value 
     * @return self
     */
    public function setControllerName($value);

    /**
     * @return string
     */
    public function getActionName();

    /**
     * @param string $value 
     * @return self
     */
    public function setActionName($value);

    /**
     * @return string
     */
    public function getControllerKey();

    /**
     * @param string $key 
     * @return self
     */
    public function setControllerKey($key);

    /**
     * @return string
     */
    public function getActionKey();

    /**
     * @param string $key 
     * @return self
     */
    public function setActionKey($key);

    /**
     * @param string $key 
     * @return mixed
     */
    public function getParam($key);

    /**
     * @param string $key 
     * @param mixed $value 
     * @return self
     */
    public function setParam($key, $value);

    /**
     * @return array
     */
     public function getParams();

    /**
     * @param array $array 
     * @return self
     */
    public function setParams(array $array);

    /**
     * @param boolean $flag 
     * @return self
     */
    public function setDispatched($flag = true);

    /**
     * @return boolean
     */
    public function isDispatched();
}
        

Объект запроса является контейнером для переменных запроса. Цепочке контроллеров надо знать только то, как устанавливать и получать контроллер, действие, опциональные параметры и флаг диспетчеризации. По умолчанию объект запроса будет искать в своих параметрах, используя ключи контроллера и действия, для определения текущих контроллера и действия.

Расширяйте этот класс или один из его производных классов, если вам нужен класс запроса, взаимодействующий с определенной средой для получения данных, использующихся в упомянутых выше задачах. Примерами могут быть среда HTTP, среда CLI или PHP-GTK.

    Поддержать сайт на родительском проекте КГБ