| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532 |
- <?xml version="1.0" encoding="UTF-8"?>
- <!-- Reviewed: no -->
- <sect1 id="zend.controller.router" xmlns:xi="http://www.w3.org/2001/XInclude">
- <title>Стандартный маршрутизатор</title>
- <sect2 id="zend.controller.router.introduction">
- <title>Введение</title>
- <para>
- <classname>Zend_Controller_Router_Rewrite</classname> является стандартным
- маршрутизатором фреймворка. Маршрутизация - это процесс принятия
- конечной точки URI (той части URI, которая
- идет после базового URL) и ее разложения на параметры
- для определения того, какой контроллер и какое действие этого
- контроллера должны получить запрос. Значения контроллера,
- действия и необязательных параметров сохраняются в объекте
- <classname>Zend_Controller_Request_Http</classname>, который затем
- обрабатывается диспетчером
- <classname>Zend_Controller_Dispatcher_Standard</classname>. Маршрутизация
- производится только один раз – когда вначале
- получен запрос и до того, как первый контроллер будет запущен.
- </para>
- <para>
- <classname>Zend_Controller_Router_Rewrite</classname> спроектирован для
- того, чтобы обеспечить функциональность, подобную mod_rewrite,
- с использованием чистого PHP. Он отчасти основан на маршрутизации,
- используемой в Ruby on Rails и не требует каких-либо предварительных
- знаний о перезаписи URL веб-сервером. Он спроектирован для работы с
- единственным правилом mod_rewrite, пример которого приведен
- ниже:
- </para>
- <programlisting language="php"><![CDATA[
- RewriteEngine on
- RewriteRule !\.(js|ico|gif|jpg|png|css|html)$ index.php
- ]]></programlisting>
- <para>
- или (более предпочтительный вариант):
- </para>
- <programlisting language="php"><![CDATA[
- RewriteEngine On
- RewriteCond %{REQUEST_FILENAME} -s [OR]
- RewriteCond %{REQUEST_FILENAME} -l [OR]
- RewriteCond %{REQUEST_FILENAME} -d
- RewriteRule ^.*$ - [NC,L]
- RewriteRule ^.*$ index.php [NC,L]
- ]]></programlisting>
- <para>
- Rewrite Router может также использоваться с веб-сервером IIS версии
- 7.0 и ниже, если
- <ulink url="http://www.isapirewrite.com">Isapi_Rewrite</ulink>
- был установлен как расширение Isapi со следующими правилами
- перезаписи:
- </para>
- <programlisting language="php"><![CDATA[
- RewriteRule ^[\w/\%]*(?:\.(?!(?:js|ico|gif|jpg|png|css|html)$)[\w\%]*$)? /index.php [I]
- ]]></programlisting>
- <note>
- <title>IIS Isapi_Rewrite</title>
- <para>
- Если используется IIS, то <varname>$_SERVER['REQUEST_URI']</varname>
- не будет определен, либо будет установлен как пустая
- строка. В этом случае
- <classname>Zend_Controller_Request_Http</classname> попытается
- использовать <varname>$_SERVER['HTTP_X_REWRITE_URL']</varname>,
- значение которого устанавливается расширением Isapi_Rewrite.
- </para>
- </note>
- <para>
- IIS 7.0 имеет свой собственный модуль перезаписи URL,
- и он может быть сконфигурирован следующим образом:
- </para>
- <programlisting language="xml"><![CDATA[
- <?xml version="1.0" encoding="UTF-8"?>
- <configuration>
- <system.webServer>
- <rewrite>
- <rules>
- <rule name="Imported Rule 1" stopProcessing="true">
- <match url="^.*$" />
- <conditions logicalGrouping="MatchAny">
- <add input="{REQUEST_FILENAME}"
- matchType="IsFile" pattern=""
- ignoreCase="false" />
- <add input="{REQUEST_FILENAME}"
- matchType="IsDirectory"
- pattern="" ignoreCase="false" />
- </conditions>
- <action type="None" />
- </rule>
- <rule name="Imported Rule 2" stopProcessing="true">
- <match url="^.*$" />
- <action type="Rewrite" url="index.php" />
- </rule>
- </rules>
- </rewrite>
- </system.webServer>
- </configuration>
- ]]></programlisting>
- <para>
- Если используется Lighttpd, то корректным будет следующее
- правило перезаписи:
- </para>
- <programlisting language="lighttpd"><![CDATA[
- url.rewrite-once = (
- ".*\?(.*)$" => "/index.php?$1",
- ".*\.(js|ico|gif|jpg|png|css|html)$" => "$0",
- "" => "/index.php"
- )
- ]]></programlisting>
- </sect2>
- <sect2 id="zend.controller.router.usage">
- <title>Использование маршрутизатора</title>
- <para>
- Для того, чтобы правильно использовать маршрутизатор, вы должны
- инстанцировать его, добавить пользовательские маршруты, и внедрить
- его во фронт-контроллер. Следующий код иллюстрирует эту процедуру:
- </para>
- <programlisting language="php"><![CDATA[
- // Создание маршрутизатора
- $router = $ctrl->getRouter(); // по умолчанию возвращает rewrite router
- $router->addRoute(
- 'user',
- new Zend_Controller_Router_Route('user/:username',
- array('controller' => 'user',
- 'action' => 'info'))
- );
- ]]></programlisting>
- </sect2>
- <sect2 id="zend.controller.router.basic">
- <title>Базовые операции Rewrite Router</title>
- <para>
- Сущностью RewriteRouter (перезаписывающий маршрутизатор) является
- определение пользовательских маршрутов. Маршруты добавляются
- посредством вызовом метода <code>addRoute()</code> и передачей ему
- экземпляра класса, реализующего
- <classname>Zend_Controller_Router_Route</classname>. Например:
- </para>
- <programlisting language="php"><![CDATA[
- $router->addRoute('user',
- new Zend_Controller_Router_Route('user/:username'));
- ]]></programlisting>
- <para>
- Rewrite Router поставляется вместе с шестью базовыми типами
- маршрутов (один из которых является специальным):
- </para>
- <itemizedlist mark="opencircle">
- <listitem><para>
- <xref linkend="zend.controller.router.routes.standard" />
- </para></listitem>
- <listitem><para>
- <xref linkend="zend.controller.router.routes.static" />
- </para></listitem>
- <listitem><para>
- <xref linkend="zend.controller.router.routes.regex" />
- </para></listitem>
- <listitem><para>
- <xref linkend="zend.controller.router.routes.hostname" />
- </para></listitem>
- <listitem><para>
- <xref linkend="zend.controller.router.routes.chain" />
- </para></listitem>
- <listitem><para>
- <xref linkend="zend.controller.router.default-routes" /> *
- </para></listitem>
- </itemizedlist>
- <para>
- Маршруты могут использоваться несколько раз для создания цепочки или
- пользовательской схемы маршрутизации в приложении. Вы можете
- использовать любое количество маршрутов в любой конфигурации, за
- исключением маршрута Module, который предпочтительно должен
- использоваться один раз и, возможно, как наиболее общий маршрут
- (например, в качестве используемого по умолчанию). Каждый маршрут
- будет в подробностях описан ниже.
- </para>
- <para>
- Первым параметром метода <code>addRoute()</code> является имя
- маршрута. Он используется в качестве идентификатора для получения
- маршрутов из маршрутизатора (например, в целях генерации URL).
- Вторым параметром является сам маршрут.
- </para>
- <note>
- <para>
- Наиболее часто имя маршрута используется через хелпер для URL
- компоненты <classname>Zend_View</classname>:
- </para>
- <programlisting language="php"><![CDATA[
- <a href=
- "<?php echo $this->url(array('username' => 'martel'), 'user') ?>">Martel</a>
- ]]></programlisting>
- <para>
- В результате значением атрибута href будет
- <code>user/martel</code>.
- </para>
- </note>
- <para>
- Маршрутизация - простой процесс итерации по всем предоставленным
- маршрутам и сопоставления их определений с текущим URI запроса.
- Когда найдено соответствие, то из объекта маршрута возвращаются
- значения переменных и добавляются в объект
- <classname>Zend_Controller_Request</classname> для дальнейшего использования в
- диспетчере и пользовательских контроллерах. Если соответствие не
- найдено, то проверяется следующий маршрут в цепочке.
- </para>
- <para>
- Если нужно определить выбранный маршрут,
- то можно использовать метод <code>getCurrentRouteName()</code>,
- он возвращает идентификатор, который использовался при регистрации
- маршрута в маршрутизаторе. Если требуется получить объект,
- то используйте <code>getCurrentRoute()</code>.
- </para>
- <note>
- <title>Обратный порядок сопоставления</title>
- <para>
- Маршруты сопоставляются в обратном порядке, поэтому
- удостоверьтесь, что наиболее общие маршруты определены
- первыми.
- </para>
- </note>
- <note>
- <title>Возвращаемые значения</title>
- <para>
- Значения, возвращаемые при маршрутизации, получаются из
- параметров URL или определенных пользователем значений по
- умолчанию. Эти переменные позднее могут быть позднее получены
- через методы <code>Zend_Controller_Request::getParam()</code>
- и <code>Zend_Controller_Action::_getParam()</code>
- </para>
- </note>
- <para>
- Есть три специальные переменные, которые могут использоваться в
- маршрутах: 'module', 'controller' и 'action'. Эти
- переменные используются диспетчером <classname>Zend_Controller_Dispatcher</classname>
- для нахождения контроллера и действия, которым передается
- управление.
- </para>
- <note>
- <title>Специальные переменные</title>
- <para>
- Имена этих переменных могут быть другими, если вы измените их
- через методы <code>setControllerKey</code> и
- <code>setActionKey</code>.
- </para>
- </note>
- </sect2>
- <sect2 id="zend.controller.router.default-routes">
- <title>Маршруты, используемые по умолчанию</title>
- <para>
- <classname>Zend_Controller_Router_Rewrite</classname> изначально
- сконфигурирован с одним маршрутом по умолчанию, который будет
- соответствовать URI вида <code>контроллер/действие</code>. Кроме
- того, в качестве первого элемента пути может быть указано имя
- модуля, это позволяет использовать URI вида
- <code>модуль/контроллер/действие</code>.
- Этот маршрут будет также соответствовать любым дополнительным
- параметрам, по умолчанию добавляемым в конец URI -
- <code>контроллер/действие/переменная1/значение1/переменная2/значение2</code>.
- </para>
- <para>
- Некоторые примеры того, чему будут соответствовать такие маршруты:
- </para>
- <programlisting language="php"><![CDATA[
- // Допустим, есть следующие настройки:
- $ctrl->setControllerDirectory(
- array(
- 'default' => '/path/to/default/controllers',
- 'news' => '/path/to/news/controllers',
- 'blog' => '/path/to/blog/controllers'
- )
- );
- Только модуль:
- http://example/news
- module == news
- Если модуль не найден, то считается, что это имя контроллера:
- http://example/foo
- controller == foo
- Модуль + контроллер:
- http://example/blog/archive
- module == blog
- controller == archive
- Модуль + контроллер + действие:
- http://example/blog/archive/list
- module == blog
- controller == archive
- action == list
- Модуль + контроллер + действие + параметры:
- http://example/blog/archive/list/sort/alpha/date/desc
- module == blog
- controller == archive
- action == list
- sort == alpha
- date == desc
- ]]></programlisting>
- <para>
- Маршрутом, используемым по умолчанию, является объект
- <classname>Zend_Controller_Router_Route_Module</classname>, сохраненный в
- RewriteRouter под именем (индексом) 'default'. Он создается
- приблизительно следующим образом:
- </para>
- <programlisting language="php"><![CDATA[
- $compat = new Zend_Controller_Router_Route_Module(array(),
- $dispatcher,
- $request);
- $this->addRoute('default', $compat);
- ]]></programlisting>
- <para>
- Если вы не хотите использовать этот маршрут по умолчанию в своей
- схеме маршрутизации, то можете переопределить его путем создания
- собственного маршрута по умолчанию (т.е. сохранения его под именем
- 'default') или полностью удалить его через метод
- <code>removeDefaultRoutes()</code>:
- </para>
- <programlisting language="php"><![CDATA[
- // Удаление всех маршрутов по умолчанию
- $router->removeDefaultRoutes();
- ]]></programlisting>
- </sect2>
- <sect2 id="zend.controller.router.rewritebase">
- <title>Базовый URL и поддиректории</title>
- <para>
- RewriteRouter может использоваться в поддиректориях (например,
- <code>http://domain.com/~user/application-root/</code>), в этом
- случае базовый URL приложения (<code>/~user/application-root</code>)
- должен автоматически определяться в объекте
- <classname>Zend_Controller_Request_Http</classname> и соответствующим образом
- использоваться.
- </para>
- <para>
- Если базовый URL определяется некорректно, то вы можете
- переопределить его через метод <code>setBaseUrl()</code> объекта
- <classname>Zend_Controller_Request_Http</classname> (см.
- <xref linkend="zend.controller.request.http.baseurl" />):
- </para>
- <programlisting language="php"><![CDATA[
- $request->setBaseUrl('/~user/application-root/');
- ]]></programlisting>
- </sect2>
- <sect2 id="zend.controller.router.global.parameters">
- <title>Глобальные параметры</title>
- <para>
- Используя метод <code>setGlobalParam</code>, вы можете устанавливать
- глобальные параметры в маршрутизаторе, которые будут автоматически
- подставляться в маршрут при сборке. Если был установлен глобальный
- параметр, но при сборке тот же параметр был передан напрямую,
- то переданное значение параметра заменяет собой глобальное.
- Вы можете устанавливать глобальный параметр следующим образом:
- </para>
- <programlisting language="php"><![CDATA[
- $router->setGlobalParam('lang', 'en');
- ]]></programlisting>
- </sect2>
- <sect2 id="zend.controller.router.routes">
- <title>Типы маршрутов</title>
- <xi:include href="Zend_Controller-Router-Route.xml">
- <xi:fallback><xi:include href="../../en/module_specs/Zend_Controller-Router-Route.xml" /></xi:fallback>
- </xi:include>
- <xi:include href="Zend_Controller-Router-Route-Static.xml">
- <xi:fallback><xi:include href="../../en/module_specs/Zend_Controller-Router-Route-Static.xml" /></xi:fallback>
- </xi:include>
- <xi:include href="Zend_Controller-Router-Route-Regex.xml">
- <xi:fallback><xi:include href="../../en/module_specs/Zend_Controller-Router-Route-Regex.xml" /></xi:fallback>
- </xi:include>
- <xi:include href="Zend_Controller-Router-Route-Hostname.xml">
- <xi:fallback><xi:include href="../../en/module_specs/Zend_Controller-Router-Route-Hostname.xml" /></xi:fallback>
- </xi:include>
- <xi:include href="Zend_Controller-Router-Route-Chain.xml">
- <xi:fallback><xi:include href="../../en/module_specs/Zend_Controller-Router-Route-Chain.xml" /></xi:fallback>
- </xi:include>
- </sect2>
- <sect2 id="zend.controller.router.add-config">
- <title>Использование Zend_Config вместе с RewriteRouter</title>
- <para>
- Иногда может быть более удобным обновлять конфигурационный файл
- с новыми маршрутами, чем изменять код. Это возможно благодаря методу
- <code>addConfig()</code>. В сущности, вы создаете конфигурацию,
- совместимую с <classname>Zend_Config</classname>, считываете ее в своем коде и
- передаете RewriteRouter.
- </para>
- <para>
- В качестве примера рассмотрим следующий INI-файл:
- </para>
- <programlisting language="php"><![CDATA[
- [production]
- routes.archive.route = "archive/:year/*"
- routes.archive.defaults.controller = archive
- routes.archive.defaults.action = show
- routes.archive.defaults.year = 2000
- routes.archive.reqs.year = "\d+"
- routes.news.type = "Zend_Controller_Router_Route_Static"
- routes.news.route = "news"
- routes.news.defaults.controller = "news"
- routes.news.defaults.action = "list"
- routes.archive.type = "Zend_Controller_Router_Route_Regex"
- routes.archive.route = "archive/(\d+)"
- routes.archive.defaults.controller = "archive"
- routes.archive.defaults.action = "show"
- routes.archive.map.1 = "year"
- ; ИЛИ: routes.archive.map.year = 1
- ]]></programlisting>
- <para>
- Этот INI-файл может быть затем прочитан в объект
- <classname>Zend_Config</classname> как показано ниже:
- </para>
- <programlisting language="php"><![CDATA[
- $config = new Zend_Config_Ini('/path/to/config.ini', 'production');
- $router = new Zend_Controller_Router_Rewrite();
- $router->addConfig($config, 'routes');
- ]]></programlisting>
- <para>
- В примере выше мы говорим маршрутизатору, чтобы он использовал
- раздел 'routes' в файле INI для своих маршрутов. Ключ первого уровня
- в этом разделе используется для определения имени маршрута, в
- примере выше определяются маршруты 'archive' и
- 'news'. Каждый маршрут требует, как минимум, запись 'route' и
- одну или более записей 'defaults'; опционально может быть одна
- или более записей 'reqs' (сокращение от 'required'). Все это
- соответствует трем аргументам, передаваемым объекту
- <classname>Zend_Controller_Router_Route_Interface</classname>.
- Опция с ключом 'type' может использоваться для определения класса,
- используемого для данного маршрута; по умолчанию используется
- класс <classname>Zend_Controller_Router_Route</classname>. В примере выше
- для маршрута 'news' должен использоваться класс
- <classname>Zend_Controller_Router_Route_Static</classname>.
- </para>
- </sect2>
- <sect2 id="zend.controller.router.subclassing">
- <title>Создание подклассов маршрутизатора</title>
- <para>
- Стандартный RewriteRouter создан с тем, чтобы предоставлять полный
- набор тех функциональных возможностей, которые могут вам
- понадобиться. Как правило, вам нужно будет только создать новый тип
- маршрута для того, чтобы получить новый или измененный функционал
- сверх уже существующих типов маршрутов.
- </para>
- <para>
- В какой-то момент вы можете захотеть использовать другую парадигму
- маршрутизации. Интерфейс
- <classname>Zend_Controller_Router_Interface</classname> дает минимальную
- информацию, необходимую для создания маршрута и содержит всего один
- метод.
- </para>
- <programlisting language="php"><![CDATA[
- interface Zend_Controller_Router_Interface
- {
- /**
- * @param Zend_Controller_Request_Abstract $request
- * @throws Zend_Controller_Router_Exception
- * @return Zend_Controller_Request_Abstract
- */
- public function route(Zend_Controller_Request_Abstract $request);
- }
- ]]></programlisting>
- <para>
- Маршрутизация производится только один раз - когда в систему
- поступил первый запрос. Назначение маршрутизатора состоит в
- определении контроллера, действия и опциональных параметров,
- основываясь на переменных запроса, и установке их в запросе. Затем
- объект запроса передается диспетчеру. Если не найден соответствующий
- маршрут, то маршрутизатор не должен ничего делать с объектом
- запроса.
- </para>
- </sect2>
- </sect1>
- <!--
- vim:se ts=4 sw=4 et:
- -->
|