<?xml version="1.0" encoding="UTF-8"?>
<!-- Reviewed: no -->
<sect1 id="zend.controller.request">
    <title>Объект запроса</title>
    <sect2 id="zend.controller.request.introduction">
        <title>Введение</title>
        <para>
            Объект запроса - это простой "объект значений"
            (<ulink url="http://www.patternsforphp.com/wiki/Value_Object">value
            object</ulink>), который передается между
            <classname>Zend_Controller_Front</classname>, маршрутизатором,
            диспетчером и контроллерами. Он хранит в себе имена запрошенных
            модуля, контроллера, действия и необязательные параметры, а также
            остальную среду (переменные) запроса, будь это HTTP, CLI или
            PHP-GTK.
        </para>

        <itemizedlist>
            <listitem><para>
                Доступ к имени модуля производится через
                <code>getModuleName()</code> и <code>setModuleName()</code>.
            </para></listitem>

            <listitem><para>
                Доступ к имени контроллера производится через
                <code>getControllerName()</code> и
                <code>setControllerName()</code>.
            </para></listitem>

            <listitem><para>
                Доступ к имени действия производится через
                <code>getActionName()</code> и
                <code>setActionName()</code>.
            </para></listitem>

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

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

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

        <para>
            Кроме того, объект запроса очень полезен в тестировании.
            Разработчик может вручную установить переменные запроса, включая
            модуль, контроллер, действие, параметры, URI и т.д., и передать
            объект запроса фронт-контроллеру для проверки процесса выполнения
            приложения. Если комбинировать его с
            <link linkend="zend.controller.response">объектом ответа</link>,
            то становится возможным тщательное и точное юнит-тестирование
            приложений MVC.
        </para>
    </sect2>

    <sect2 id="zend.controller.request.http">
        <title>HTTP-запросы</title>

        <sect3 id="zend.controller.request.http.dataacess">
            <title>Доступ к данным запроса</title>

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

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

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

            <note>
                <title>Данные GET и POST</title>
                <para>
                    Будьте осторожны, когда извлекаете данные из объекта
                    запроса, поскольку они совсем не фильтруются. Маршрутизатор
                    и диспетчер производят проверку на допустимость и фильтрацию
                    данных для использования в своих целях, но оставляют их
                    нетронутыми в объекте запроса.
                </para>
            </note>

            <note>
                <title>Извлечение Raw POST данных</title>

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

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

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

            <note>
                <title>getParam() извлекает не только пользовательские
                параметры</title>

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

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

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

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

                <programlisting language="php"><![CDATA[
$request = new Zend_Controller_Request_Apache404();
$front->setRequest($request);
]]></programlisting>

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

        </sect3>

        <sect3 id="zend.controller.request.http.baseurl">
            <title>Базовый URL и поддиректории</title>

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

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

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

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

            <programlisting language="php"><![CDATA[
/**
 * Обработка запроса со своим базовым 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();
]]></programlisting>

        </sect3>

        <sect3 id="zend.controller.request.http.method">
            <title>Определение HTTP-метода запроса</title>

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

            <itemizedlist>
                <listitem><para><code>isGet()</code></para></listitem>
                <listitem><para><code>isPost()</code></para></listitem>
                <listitem><para><code>isPut()</code></para></listitem>
                <listitem><para><code>isDelete()</code></para></listitem>
                <listitem><para><code>isHead()</code></para></listitem>
                <listitem><para><code>isOptions()</code></para></listitem>
            </itemizedlist>

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

        <sect3 id="zend.controller.request.http.ajax">
            <title>Определение запросов AJAX</title>

            <para>
                <classname>Zend_Controller_Request_Http</classname> имеет
                рудиментарный метод
                для определения запросов AJAX: <code>isXmlHttpRequest()</code>.
                Этот метод проверяет наличие заголовка HTTP-запроса
                <code>X-Requested-With</code> со значением 'XMLHttpRequest'.
                Если он найден, то возвращается <constant>TRUE</constant>.
            </para>

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

            <itemizedlist>
                <listitem><para>Prototype/Scriptaculous (и библиотеки, производные от Prototype)</para></listitem>
                <listitem><para>Yahoo! UI Library</para></listitem>
                <listitem><para>jQuery</para></listitem>
                <listitem><para>MochiKit</para></listitem>
            </itemizedlist>

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

    <sect2 id="zend.controller.request.subclassing">
        <title>Создание подклассов объекта запроса</title>

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

        <programlisting language="php"><![CDATA[
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();
}
]]></programlisting>

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

        <para>
            Расширяйте этот класс или один из его производных классов, если вам
            нужен класс запроса, взаимодействующий с определенной средой для
            получения данных, использующихся в упомянутых выше задачах.
            Примерами могут быть <link
            linkend="zend.controller.request.http">среда
            HTTP</link>, среда CLI или PHP-GTK.
        </para>
    </sect2>
</sect1>
<!--
vim:se ts=4 sw=4 et:
-->
