| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266 |
- <?xml version="1.0" encoding="UTF-8"?>
- <!-- Reviewed: no -->
- <sect3 id="zend.controller.router.routes.regex">
- <title>Zend_Controller_Router_Route_Regex</title>
- <para>
- Кроме описанных ранее типов маршрутов - используемого по умолчанию и
- статического - есть маршруты на регулярных выражениях. Этот маршрут
- дает больше мощности и гибкости, чем другие типы маршрутов, но
- ценой некоторой дополнительной сложности. В то же время он должен быть
- более быстрым, чем стандартный маршрут.
- </para>
- <para>
- Как и в случае стандартного, такой маршрут должен быть
- проинициализирован с определением маршрута и некоторыми значениями по
- умолчанию. Давайте в качестве примера создадим маршрут для архива, такой
- же, как в предыдущих примерах, но на этот раз с использованием маршрута
- Regex:
- </para>
- <programlisting language="php"><![CDATA[
- $route = new Zend_Controller_Router_Route_Regex(
- 'archive/(\d+)',
- array(
- 'controller' => 'archive',
- 'action' => 'show'
- )
- );
- $router->addRoute('archive', $route);
- ]]></programlisting>
- <para>
- Каждый определенный подшаблон регулярного выражения будет внедрен в
- объект запроса. В нашем примере после успешного сопоставления с
- <code>http://domain.com/archive/2006</code> результирующий массив
- значений может выглядеть следующим образом:
- </para>
- <programlisting language="php"><![CDATA[
- $values = array(
- 1 => '2006',
- 'controller' => 'archive',
- 'action' => 'show'
- );
- ]]></programlisting>
- <note>
- <para>
- Ведущая и замыкающая косые черты удаляются из URL в маршрутизаторе
- до сопоставления. Поэтому URL-у
- <code>http://domain.com/foo/bar/</code> будет соответствовать
- регулярное выражение <code>foo/bar</code>, но не
- <code>/foo/bar</code>.
- </para>
- </note>
- <note>
- <para>
- Указатели начала и конца строки ('^' и '$' соответственно)
- автоматически добавляются в начало и конец всех выражений. Поэтому
- вы не должны использовать их в своих регулярных выражениях, кроме
- этого, следует передавать строку выражения целиком.
- </para>
- </note>
- <note>
- <para>
- Этот класс маршрута использует символ <code>#</code> в качестве
- ограничителя. Это означает, что нужно экранировать символы хэша
- ('#'), но не прямой косой черты ('/') в своем определении маршрута.
- Поскольку символ '#' (называемый анкером) редко передается
- веб-серверу, вам нечасто придется использовать этот символ в своем
- регулярном выражении.
- </para>
- </note>
- <para>
- Вы можете получать содержимое заданного подшаблона обычным способом:
- </para>
- <programlisting language="php"><![CDATA[
- public function showAction()
- {
- $request = $this->getRequest();
- $year = $request->getParam(1); // $year = '2006';
- }
- ]]></programlisting>
- <note>
- <para>
- Обратите внимание, что ключ является целым числом (1), а не строкой ('1').
- </para>
- </note>
- <para>
- Этот маршрут не будет работать в точности так же, как и аналогичный ему
- стандартный маршрут, потому что еще не определено значение по умолчанию
- для 'year'. Есть еще неочевидная проблема с замыкающей косой чертой,
- которая остается даже в том случае, если мы объявим значение по
- умолчанию для 'year' и сделаем подшаблон опциональным. Решение состоит в
- том, чтобы сделать часть 'year' опциональной вместе с косой чертой, но
- отлавливать только число:
- </para>
- <programlisting language="php"><![CDATA[
- $route = new Zend_Controller_Router_Route_Regex(
- 'archive(?:/(\d+))?',
- array(
- 1 => '2006',
- 'controller' => 'archive',
- 'action' => 'show'
- )
- );
- $router->addRoute('archive', $route);
- ]]></programlisting>
- <para>
- А теперь давайте обратимся к проблеме, которую вы, должно быть, заметили
- сами. Использование целочисленных ключей для параметров не является
- легко управляемым решением и потенциально проблематично в долговременном
- использовании. Вот тут на сцену выходит третий параметр. Этот параметр
- является ассоциативным массивом, представляющий соответствие подшаблонов
- регулярного выражения именованным ключам параметров. Доработаем наш
- простой пример:
- </para>
- <programlisting language="php"><![CDATA[
- $route = new Zend_Controller_Router_Route_Regex(
- 'archive/(\d+)',
- array(
- 'controller' => 'archive',
- 'action' => 'show'
- ),
- array(
- 1 => 'year'
- )
- );
- $router->addRoute('archive', $route);
- ]]></programlisting>
- <para>
- Это приведет к тому, что в объект запроса будут добавлены следующие
- значения:
- </para>
- <programlisting language="php"><![CDATA[
- $values = array(
- 'year' => '2006',
- 'controller' => 'archive',
- 'action' => 'show'
- );
- ]]></programlisting>
- <para>
- Для того, чтобы соответствия работали в любом окружении, они могут быть
- определены в любом направлении. Ключи массива могут содержать как имена
- переменных, так и индексы подшаблонов:
- </para>
- <programlisting language="php"><![CDATA[
- $route = new Zend_Controller_Router_Route_Regex(
- 'archive/(\d+)',
- array( ... ),
- array(1 => 'year')
- );
- // ИЛИ
- $route = new Zend_Controller_Router_Route_Regex(
- 'archive/(\d+)',
- array( ... ),
- array('year' => 1)
- );
- ]]></programlisting>
- <note>
- <para>
- Ключи подшаблонов должны быть представлены целыми числами.
- </para>
- </note>
- <para>
- Обратите внимание, что числовой индекс в значениях объекта запроса
- теперь отсутствует и вместо него присутствует именованная переменная.
- Конечно, при желании вы можете смешивать числовые и именованные ключи:
- </para>
- <programlisting language="php"><![CDATA[
- $route = new Zend_Controller_Router_Route_Regex(
- 'archive/(\d+)/page/(\d+)',
- array( ... ),
- array('year' => 1)
- );
- ]]></programlisting>
- <para>
- Это приведет к тому, что в объекте запроса будут значения с разными
- ключами. Например, при URL
- <code>http://domain.com/archive/2006/page/10</code> результатом будут
- следующие значения:
- </para>
- <programlisting language="php"><![CDATA[
- $values = array(
- 'year' => '2006',
- 2 => 10,
- 'controller' => 'archive',
- 'action' => 'show'
- );
- ]]></programlisting>
- <para>
- Поскольку регулярные выражения трудно реверсировать, то вам нужно будет
- подготовить реверсный URL, если хотите использовать хелпер для URL, или
- даже написать метод этого класса. Реверсный путь представляется строкой,
- оформленной для использования с функцией sprintf(), и определенной как
- четвертый параметр конструктора:
- </para>
- <programlisting language="php"><![CDATA[
- $route = new Zend_Controller_Router_Route_Regex(
- 'archive/(\d+)',
- array( ... ),
- array('year' => 1),
- 'archive/%s'
- );
- ]]></programlisting>
- <para>
- Все это можно реализовать через объект стандартного маршрута, поэтому вы
- спросите - какие преимущества дает использование маршрута Regex? Главным
- образом, он позволяет описывать любые типы URL без всяких ограничений.
- Предположим, у вас есть свой блог, вы хотите создавать URL вида
- <code>http://domain.com/blog/archive/01-Using_the_Regex_Router.html</code>
- и должны разлагать последний элемент пути
- <code>01-Using_the_Regex_Router.html</code> на ID статьи и ее
- заголовок/описание. Это невозможно реализовать с помощью стандартного
- маршрута. С маршрутом Regex вы можете сделать нечто подобное для решения
- этой задачи:
- </para>
- <programlisting language="php"><![CDATA[
- $route = new Zend_Controller_Router_Route_Regex(
- 'blog/archive/(\d+)-(.+)\.html',
- array(
- 'controller' => 'blog',
- 'action' => 'view'
- ),
- array(
- 1 => 'id',
- 2 => 'description'
- ),
- 'blog/archive/%d-%s.html'
- );
- $router->addRoute('blogArchive', $route);
- ]]></programlisting>
- <para>
- Как вы можете видеть, маршруты Regex дают несравненно большую гибкость
- по сравнению со стандартными маршрутами.
- </para>
- </sect3>
- <!--
- vim:se ts=4 sw=4 et:
- -->
|