[ZF-10089] Zend_Log
[zend.git] / documentation / manual / en / module_specs / Zend_Controller-Router-Route-Regex.xml
blobc78937efac79662d9c8dac2249c966f7b37c5be1
1 <?xml version="1.0" encoding="UTF-8"?>
2 <!-- Reviewed: no -->
3 <sect3 id="zend.controller.router.routes.regex">
4     <title>Zend_Controller_Router_Route_Regex</title>
6     <para>
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.
11     </para>
13     <para>
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
17         route this time:
18     </para>
20     <programlisting language="php"><![CDATA[
21 $route = new Zend_Controller_Router_Route_Regex(
22     'archive/(\d+)',
23     array(
24         'controller' => 'archive',
25         'action'     => 'show'
26     )
28 $router->addRoute('archive', $route);
29 ]]></programlisting>
31     <para>
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
35         array may look like:
36     </para>
38     <programlisting language="php"><![CDATA[
39 $values = array(
40     1            => '2006',
41     'controller' => 'archive',
42     'action'     => 'show'
44 ]]></programlisting>
46     <note>
47         <para>
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>.
52         </para>
53     </note>
55     <note>
56         <para>
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.
61         </para>
62     </note>
64     <note>
65         <para>
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.
71         </para>
72     </note>
74     <para>
75         You can get the contents of the defined subpatterns the usual way:
76     </para>
78     <programlisting language="php"><![CDATA[
79 public function showAction()
81     $request = $this->getRequest();
82     $year    = $request->getParam(1); // $year = '2006';
84 ]]></programlisting>
86     <note>
87         <para>Notice the key is an integer (1) instead of a string ('1').</para>
88     </note>
90     <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:
97     </para>
99     <programlisting language="php"><![CDATA[
100 $route = new Zend_Controller_Router_Route_Regex(
101     'archive(?:/(\d+))?',
102     array(
103         1            => '2006',
104         'controller' => 'archive',
105         'action'     => 'show'
106     )
108 $router->addRoute('archive', $route);
109 ]]></programlisting>
111     <para>
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:
118     </para>
120     <programlisting language="php"><![CDATA[
121 $route = new Zend_Controller_Router_Route_Regex(
122     'archive/(\d+)',
123     array(
124         'controller' => 'archive',
125         'action' => 'show'
126     ),
127     array(
128         1 => 'year'
129     )
131 $router->addRoute('archive', $route);
132 ]]></programlisting>
134     <para>
135         This will result in following values injected into Request:
136     </para>
138     <programlisting language="php"><![CDATA[
139 $values = array(
140     'year'       => '2006',
141     'controller' => 'archive',
142     'action'     => 'show'
144 ]]></programlisting>
146     <para>
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:
149     </para>
151     <programlisting language="php"><![CDATA[
152 $route = new Zend_Controller_Router_Route_Regex(
153     'archive/(\d+)',
154     array( ... ),
155     array(1 => 'year')
158 // OR
160 $route = new Zend_Controller_Router_Route_Regex(
161     'archive/(\d+)',
162     array( ... ),
163     array('year' => 1)
165 ]]></programlisting>
167     <note>
168         <para>
169             Subpattern keys have to be represented by integers.
170         </para>
171     </note>
173     <para>
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:
177     </para>
179     <programlisting language="php"><![CDATA[
180 $route = new Zend_Controller_Router_Route_Regex(
181     'archive/(\d+)/page/(\d+)',
182     array( ... ),
183     array('year' => 1)
185 ]]></programlisting>
187     <para>
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:
191     </para>
193     <programlisting language="php"><![CDATA[
194 $values = array(
195     'year'       => '2006',
196     2            => 10,
197     'controller' => 'archive',
198     'action'     => 'show'
200 ]]></programlisting>
202     <para>
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:
207     </para>
209     <programlisting language="php"><![CDATA[
210 $route = new Zend_Controller_Router_Route_Regex(
211     'archive/(\d+)',
212     array( ... ),
213     array('year' => 1),
214     'archive/%s'
216 ]]></programlisting>
218     <para>
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:
228     </para>
230     <programlisting language="php"><![CDATA[
231 $route = new Zend_Controller_Router_Route_Regex(
232     'blog/archive/(\d+)-(.+)\.html',
233     array(
234         'controller' => 'blog',
235         'action'     => 'view'
236     ),
237     array(
238         1 => 'id',
239         2 => 'description'
240     ),
241     'blog/archive/%d-%s.html'
243 $router->addRoute('blogArchive', $route);
244 ]]></programlisting>
246     <para>
247         As you can see, this adds a tremendous amount of flexibility over the
248         standard route.
249     </para>
250 </sect3>
251 <!--
252 vim:se ts=4 sw=4 et: