| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253 |
- <?xml version="1.0" encoding="UTF-8"?>
- <!-- Reviewed: no -->
- <sect3 id="zend.controller.router.routes.regex">
- <title>Zend_Controller_Router_Route_Regex</title>
- <para>
- In addition to the default and static route types, a Regular
- Expression route type is available. This route offers more power and
- flexibility over the others, but at a slight cost of complexity. At the
- same time, it should be faster than the standard Route.
- </para>
- <para>
- Like the standard route, this route has to be initialized with a route
- definition and some defaults. Let's create an archive route as an
- example, similar to the previously defined one, only using the Regex
- route this time:
- </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>
- Every defined regex subpattern will be injected to the request
- object. With our above example, after successful matching
- <filename>http://domain.com/archive/2006</filename>, the resulting value
- array may look like:
- </para>
- <programlisting language="php"><![CDATA[
- $values = array(
- 1 => '2006',
- 'controller' => 'archive',
- 'action' => 'show'
- );
- ]]></programlisting>
- <note>
- <para>
- Leading and trailing slashes are trimmed from the <acronym>URL</acronym> in the Router
- prior to a match. As a result, matching the <acronym>URL</acronym>
- <filename>http://domain.com/foo/bar/</filename>, would involve a regex of
- <filename>foo/bar</filename>, and not <filename>/foo/bar</filename>.
- </para>
- </note>
- <note>
- <para>
- Line start and line end anchors ('^' and '$', respectively) are
- automatically pre- and appended to all expressions. Thus, you
- should not use these in your regular expressions, and you should
- match the entire string.
- </para>
- </note>
- <note>
- <para>
- This route class uses the '<emphasis>#</emphasis>' character for a delimiter.
- This means that you will need to escape hash characters ('#') but
- not forward slashes ('/') in your route definitions. Since the '#'
- character (named anchor) is rarely passed to the webserver, you will
- rarely need to use that character in your regex.
- </para>
- </note>
- <para>
- You can get the contents of the defined subpatterns the usual way:
- </para>
- <programlisting language="php"><![CDATA[
- public function showAction()
- {
- $request = $this->getRequest();
- $year = $request->getParam(1); // $year = '2006';
- }
- ]]></programlisting>
- <note>
- <para>Notice the key is an integer (1) instead of a string ('1').</para>
- </note>
- <para>
- This route will not yet work exactly the same as its standard route
- counterpart since the default for 'year' is not yet set. And what may
- not yet be evident is that we will have a problem with a trailing slash
- even if we declare a default for the year and make the subpattern
- optional. The solution is to make the whole year part optional along
- with the slash but catch only the numeric part:
- </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>
- Now let's get to the problem you have probably noticed on your own by
- now. Using integer based keys for parameters is not an easily manageable
- solution and may be potentially problematic in the long run. And that's
- where the third parameter comes in. This parameter is an associative
- array that represents a map of regex subpatterns to parameter named
- keys. Let's work on our easier example:
- </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>
- This will result in following values injected into Request:
- </para>
- <programlisting language="php"><![CDATA[
- $values = array(
- 'year' => '2006',
- 'controller' => 'archive',
- 'action' => 'show'
- );
- ]]></programlisting>
- <para>
- The map may be defined in either direction to make it work in any
- environment. Keys may contain variable names or subpattern indexes:
- </para>
- <programlisting language="php"><![CDATA[
- $route = new Zend_Controller_Router_Route_Regex(
- 'archive/(\d+)',
- array( ... ),
- array(1 => 'year')
- );
- // OR
- $route = new Zend_Controller_Router_Route_Regex(
- 'archive/(\d+)',
- array( ... ),
- array('year' => 1)
- );
- ]]></programlisting>
- <note>
- <para>
- Subpattern keys have to be represented by integers.
- </para>
- </note>
- <para>
- Notice that the numeric index in Request values is now gone and a named
- variable is shown in its place. Of course you can mix numeric and named
- variables if you wish:
- </para>
- <programlisting language="php"><![CDATA[
- $route = new Zend_Controller_Router_Route_Regex(
- 'archive/(\d+)/page/(\d+)',
- array( ... ),
- array('year' => 1)
- );
- ]]></programlisting>
- <para>
- Which will result in mixed values available in the Request. As an example, the
- <acronym>URL</acronym> <filename>http://domain.com/archive/2006/page/10</filename>
- will result in following values:
- </para>
- <programlisting language="php"><![CDATA[
- $values = array(
- 'year' => '2006',
- 2 => 10,
- 'controller' => 'archive',
- 'action' => 'show'
- );
- ]]></programlisting>
- <para>
- Since regex patterns are not easily reversed, you will need to prepare
- a reverse <acronym>URL</acronym> if you wish to use a <acronym>URL</acronym> helper or even
- an assemble method of this class. This reversed path is represented by a string parsable by
- <methodname>sprintf()</methodname> and is defined as a fourth construct parameter:
- </para>
- <programlisting language="php"><![CDATA[
- $route = new Zend_Controller_Router_Route_Regex(
- 'archive/(\d+)',
- array( ... ),
- array('year' => 1),
- 'archive/%s'
- );
- ]]></programlisting>
- <para>
- All of this is something which was already possible by the means of a
- standard route object, so where's the benefit in using the Regex route,
- you ask? Primarily, it allows you to describe any type of <acronym>URL</acronym> without
- any restrictions. Imagine you have a blog and wish to create <acronym>URL</acronym>s like:
- <filename>http://domain.com/blog/archive/01-Using_the_Regex_Router.html</filename>,
- and have it decompose the last path element,
- <filename>01-Using_the_Regex_Router.html</filename>, into an article ID and
- article title or description; this is not possible with the standard route.
- With the Regex route, you can do something like the following solution:
- </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>
- As you can see, this adds a tremendous amount of flexibility over the
- standard route.
- </para>
- </sect3>
- <!--
- vim:se ts=4 sw=4 et:
- -->
|