1 <?xml version="1.0" encoding="UTF-8"?>
3 <sect3 id="zend.controller.router.routes.regex">
4 <title>Zend_Controller_Router_Route_Regex</title>
7 In addition to the default and static route types, a Regular
8 Expression route type is available. This route offers more power and
9 flexibility over the others, but at a slight cost of complexity. At the
10 same time, it should be faster than the standard Route.
14 Like the standard route, this route has to be initialized with a route
15 definition and some defaults. Let's create an archive route as an
16 example, similar to the previously defined one, only using the Regex
20 <programlisting language="php"><![CDATA[
21 $route = new Zend_Controller_Router_Route_Regex(
24 'controller' => 'archive',
28 $router->addRoute('archive', $route);
32 Every defined regex subpattern will be injected to the request
33 object. With our above example, after successful matching
34 <filename>http://domain.com/archive/2006</filename>, the resulting value
38 <programlisting language="php"><![CDATA[
41 'controller' => 'archive',
48 Leading and trailing slashes are trimmed from the <acronym>URL</acronym> in the Router
49 prior to a match. As a result, matching the <acronym>URL</acronym>
50 <filename>http://domain.com/foo/bar/</filename>, would involve a regex of
51 <filename>foo/bar</filename>, and not <filename>/foo/bar</filename>.
57 Line start and line end anchors ('^' and '$', respectively) are
58 automatically pre- and appended to all expressions. Thus, you
59 should not use these in your regular expressions, and you should
60 match the entire string.
66 This route class uses the '<emphasis>#</emphasis>' character for a delimiter.
67 This means that you will need to escape hash characters ('#') but
68 not forward slashes ('/') in your route definitions. Since the '#'
69 character (named anchor) is rarely passed to the webserver, you will
70 rarely need to use that character in your regex.
75 You can get the contents of the defined subpatterns the usual way:
78 <programlisting language="php"><![CDATA[
79 public function showAction()
81 $request = $this->getRequest();
82 $year = $request->getParam(1); // $year = '2006';
87 <para>Notice the key is an integer (1) instead of a string ('1').</para>
91 This route will not yet work exactly the same as its standard route
92 counterpart since the default for 'year' is not yet set. And what may
93 not yet be evident is that we will have a problem with a trailing slash
94 even if we declare a default for the year and make the subpattern
95 optional. The solution is to make the whole year part optional along
96 with the slash but catch only the numeric part:
99 <programlisting language="php"><![CDATA[
100 $route = new Zend_Controller_Router_Route_Regex(
101 'archive(?:/(\d+))?',
104 'controller' => 'archive',
108 $router->addRoute('archive', $route);
112 Now let's get to the problem you have probably noticed on your own by
113 now. Using integer based keys for parameters is not an easily manageable
114 solution and may be potentially problematic in the long run. And that's
115 where the third parameter comes in. This parameter is an associative
116 array that represents a map of regex subpatterns to parameter named
117 keys. Let's work on our easier example:
120 <programlisting language="php"><![CDATA[
121 $route = new Zend_Controller_Router_Route_Regex(
124 'controller' => 'archive',
131 $router->addRoute('archive', $route);
135 This will result in following values injected into Request:
138 <programlisting language="php"><![CDATA[
141 'controller' => 'archive',
147 The map may be defined in either direction to make it work in any
148 environment. Keys may contain variable names or subpattern indexes:
151 <programlisting language="php"><![CDATA[
152 $route = new Zend_Controller_Router_Route_Regex(
160 $route = new Zend_Controller_Router_Route_Regex(
169 Subpattern keys have to be represented by integers.
174 Notice that the numeric index in Request values is now gone and a named
175 variable is shown in its place. Of course you can mix numeric and named
176 variables if you wish:
179 <programlisting language="php"><![CDATA[
180 $route = new Zend_Controller_Router_Route_Regex(
181 'archive/(\d+)/page/(\d+)',
188 Which will result in mixed values available in the Request. As an example, the
189 <acronym>URL</acronym> <filename>http://domain.com/archive/2006/page/10</filename>
190 will result in following values:
193 <programlisting language="php"><![CDATA[
197 'controller' => 'archive',
203 Since regex patterns are not easily reversed, you will need to prepare
204 a reverse <acronym>URL</acronym> if you wish to use a <acronym>URL</acronym> helper or even
205 an assemble method of this class. This reversed path is represented by a string parsable by
206 <methodname>sprintf()</methodname> and is defined as a fourth construct parameter:
209 <programlisting language="php"><![CDATA[
210 $route = new Zend_Controller_Router_Route_Regex(
219 All of this is something which was already possible by the means of a
220 standard route object, so where's the benefit in using the Regex route,
221 you ask? Primarily, it allows you to describe any type of <acronym>URL</acronym> without
222 any restrictions. Imagine you have a blog and wish to create <acronym>URL</acronym>s like:
223 <filename>http://domain.com/blog/archive/01-Using_the_Regex_Router.html</filename>,
224 and have it decompose the last path element,
225 <filename>01-Using_the_Regex_Router.html</filename>, into an article ID and
226 article title or description; this is not possible with the standard route.
227 With the Regex route, you can do something like the following solution:
230 <programlisting language="php"><![CDATA[
231 $route = new Zend_Controller_Router_Route_Regex(
232 'blog/archive/(\d+)-(.+)\.html',
234 'controller' => 'blog',
241 'blog/archive/%d-%s.html'
243 $router->addRoute('blogArchive', $route);
247 As you can see, this adds a tremendous amount of flexibility over the