File: Zend_Controller-Router.xml

package info (click to toggle)
zendframework 1.12.9%2Bdfsg-2
  • links: PTS, VCS
  • area: main
  • in suites: jessie-kfreebsd
  • size: 133,584 kB
  • sloc: xml: 1,311,829; php: 570,173; sh: 170; makefile: 125; sql: 121
file content (534 lines) | stat: -rw-r--r-- 20,733 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
<?xml version="1.0" encoding="UTF-8"?>
<!-- Reviewed: no -->
<sect1 id="zend.controller.router" xmlns:xi="http://www.w3.org/2001/XInclude">
    <title>The Standard Router</title>

    <sect2 id="zend.controller.router.introduction">
        <title>Introduction</title>

        <para>
            <classname>Zend_Controller_Router_Rewrite</classname> is the standard
            framework router. Routing is the process of taking a <acronym>URI</acronym> endpoint
            (that part of the <acronym>URI</acronym> which comes after the base
            <acronym>URL</acronym>) and decomposing it into parameters to determine which module,
            controller, and action of that controller should receive the
            request. This values of the module, controller, action and other
            parameters are packaged into a
            <classname>Zend_Controller_Request_Http</classname> object which is then
            processed by <classname>Zend_Controller_Dispatcher_Standard</classname>.
            Routing occurs only once: when the request is initially received and
            before the first controller is dispatched.
        </para>

        <para>
            <classname>Zend_Controller_Router_Rewrite</classname> is designed to allow for
            mod_rewrite-like functionality using pure <acronym>PHP</acronym> structures. It is very
            loosely based on Ruby on Rails routing and does not require any
            prior knowledge of webserver <acronym>URL</acronym> rewriting. It is designed to work
            with a single Apache mod_rewrite rule (one of):
        </para>

        <programlisting language="php"><![CDATA[
RewriteEngine on
RewriteRule !\.(js|ico|gif|jpg|png|css|html)$ index.php
]]></programlisting>

        <para>
            or (preferred):
        </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>
            The rewrite router can also be used with the <acronym>IIS</acronym> webserver (versions
            &lt;= 7.0) if <ulink url="http://www.isapirewrite.com">Isapi_Rewrite</ulink> has been
            installed as an Isapi extension with the following rewrite rule:
        </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>
                When using <acronym>IIS</acronym>, <varname>$_SERVER['REQUEST_URI']</varname> will
                either not exist, or be set as an empty string. In this case,
                <classname>Zend_Controller_Request_Http</classname> will attempt to use
                the <varname>$_SERVER['HTTP_X_REWRITE_URL']</varname> value set by the
                <classname>Isapi_Rewrite</classname> extension.
            </para>
        </note>

        <para>
            <acronym>IIS</acronym> 7.0 introduces a native <acronym>URL</acronym> rewriting module,
            and it can be configured as follows:
        </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>
            If using Lighttpd, the following rewrite rule is valid:
        </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>Using a Router</title>

        <para>
            To properly use the rewrite router you have to instantiate it, add
            some user defined routes and inject it into the controller. The
            following code illustrates the procedure:
        </para>

        <programlisting language="php"><![CDATA[
// Create a router

$router = $ctrl->getRouter(); // returns a rewrite router by default
$router->addRoute(
    'user',
    new Zend_Controller_Router_Route('user/:username',
                                     array('controller' => 'user',
                                           'action' => 'info'))
);
]]></programlisting>
    </sect2>

    <sect2 id="zend.controller.router.basic">
        <title>Basic Rewrite Router Operation</title>

        <para>
            The heart of the RewriteRouter is the definition of user defined
            routes. Routes are added by calling the addRoute method of
            RewriteRouter and passing in a new instance of a class implementing
            <classname>Zend_Controller_Router_Route_Interface</classname>. Eg.:
        </para>

        <programlisting language="php"><![CDATA[
$router->addRoute('user',
                  new Zend_Controller_Router_Route('user/:username'));
]]></programlisting>

        <para>
            Rewrite Router comes with six basic types of routes (one of which
            is special):
        </para>

        <itemizedlist mark="opencircle">
            <listitem>
                <para>
                    <link
                        linkend="zend.controller.router.routes.standard">Zend_Controller_Router_Route</link>
                </para>
            </listitem>

            <listitem>
                <para>
                    <link
                        linkend="zend.controller.router.routes.static">Zend_Controller_Router_Route_Static</link>
                </para>
            </listitem>

            <listitem>
                <para>
                    <link
                        linkend="zend.controller.router.routes.regex">Zend_Controller_Router_Route_Regex</link>
                </para>
            </listitem>

            <listitem>
                <para>
                    <link
                        linkend="zend.controller.router.routes.hostname">Zend_Controller_Router_Route_Hostname</link>
                </para>
            </listitem>

            <listitem>
                <para>
                    <link
                        linkend="zend.controller.router.routes.chain">Zend_Controller_Router_Route_Chain</link>
                </para>
            </listitem>

            <listitem>
                <para>
                    <link
                        linkend="zend.controller.router.default-routes">Zend_Controller_Router_Rewrite</link>
                    *
                </para>
            </listitem>
        </itemizedlist>

        <para>
            Routes may be used numerous times to create a chain or user defined
            application routing schema. You may use any number of routes in any
            configuration, with the exception of the Module route, which should
            rather be used once and probably as the most generic route (i.e., as a
            default). Each route will be described in greater detail later on.
        </para>

        <para>
            The first parameter to addRoute is the name of the route. It is used
            as a handle for getting the routes out of the router (e.g., for <acronym>URL</acronym>
            generation purposes). The second parameter being the route itself.
        </para>

        <note>
            <para>
                The most common use of the route name is through the means of
                <classname>Zend_View</classname> url helper:
            </para>

            <programlisting language="php"><![CDATA[
<a href=
"<?php echo $this->url(array('username' => 'martel'), 'user') ?>">Martel</a>
]]></programlisting>

            <para>
                Which would result in the href: <filename>user/martel</filename>.
            </para>
        </note>

        <para>
            Routing is a simple process of iterating through all provided routes
            and matching its definitions to current request <acronym>URI</acronym>. When a positive
            match is found, variable values are returned from the Route instance
            and are injected into the <classname>Zend_Controller_Request</classname>
            object for later use in the dispatcher as well as in user created
            controllers. On a negative match result, the next route in the chain
            is checked.
        </para>

        <para>
            If you need to determine which route was matched, you can use the
            <methodname>getCurrentRouteName()</methodname> method, which will return the
            identifier used when registering the route with the router. If you
            want the actual route object, you can use
            <methodname>getCurrentRoute()</methodname>.
        </para>

        <note>
            <title>Reverse Matching</title>

            <para>
                Routes are matched in reverse order so make sure your most
                generic routes are defined first.
            </para>
        </note>

        <note>
            <title>Returned Values</title>

            <para>
                Values returned from routing come from <acronym>URL</acronym> parameters or user
                defined route defaults. These variables are later accessible
                through the <methodname>Zend_Controller_Request::getParam()</methodname> or
                <methodname>Zend_Controller_Action::_getParam()</methodname> methods.
            </para>
        </note>

        <para>
            There are three special variables which can be used in your routes
            - 'module', 'controller' and 'action'. These special variables are
            used by <classname>Zend_Controller_Dispatcher</classname> to find a controller and
            action to dispatch to.
        </para>

        <note>
            <title>Special Variables</title>

            <para>
                The names of these special variables may be different if you
                choose to alter the defaults in
                <classname>Zend_Controller_Request_Http</classname> by means of the
                <methodname>setControllerKey()</methodname> and
                <methodname>setActionKey()</methodname> methods.
            </para>
        </note>

    </sect2>

    <sect2 id="zend.controller.router.default-routes">
        <title>Default Routes</title>

        <para>
            <classname>Zend_Controller_Router_Rewrite</classname> comes preconfigured with a default
            route, which will match <acronym>URI</acronym>s in the shape of
            <filename>controller/action</filename>. Additionally, a module name may be
            specified as the first path element, allowing <acronym>URI</acronym>s of the form
            <filename>module/controller/action</filename>. Finally, it will also match
            any additional parameters appended to the <acronym>URI</acronym> by default -
            <filename>controller/action/var1/value1/var2/value2</filename>.
        </para>

        <para>
            Some examples of how such routes are matched:
        </para>

        <programlisting language="php"><![CDATA[
// Assuming the following:
$ctrl->setControllerDirectory(
    array(
        'default' => '/path/to/default/controllers',
        'news'    => '/path/to/news/controllers',
        'blog'    => '/path/to/blog/controllers'
    )
);

Module only:
http://example/news
    module == news

Invalid module maps to controller name:
http://example/foo
    controller == foo

Module + controller:
http://example/blog/archive
    module     == blog
    controller == archive

Module + controller + action:
http://example/blog/archive/list
    module     == blog
    controller == archive
    action     == list

Module + controller + action + params:
http://example/blog/archive/list/sort/alpha/date/desc
    module     == blog
    controller == archive
    action     == list
    sort       == alpha
    date       == desc
]]></programlisting>

        <para>
            The default route is simply a
            <classname>Zend_Controller_Router_Route_Module</classname> object stored under
            the name (index) of 'default' in RewriteRouter. It's created
            more-or-less like below:
        </para>

        <programlisting language="php"><![CDATA[
$compat = new Zend_Controller_Router_Route_Module(array(),
                                                  $dispatcher,
                                                  $request);
$this->addRoute('default', $compat);
]]></programlisting>

        <para>
            If you do not want this particular default route in your routing
            schema, you may override it by creating your own 'default' route
            (i.e., storing it under the name of 'default') or removing it
            altogether by using <methodname>removeDefaultRoutes()</methodname>:
        </para>

        <programlisting language="php"><![CDATA[
// Remove any default routes
$router->removeDefaultRoutes();
]]></programlisting>
    </sect2>

    <sect2 id="zend.controller.router.rewritebase">
        <title>Base URL and Subdirectories</title>

        <para>
            The rewrite router can be used in subdirectories (e.g.,
            <filename>http://domain.com/user/application-root/</filename>) in which
            case the base <acronym>URL</acronym> of the application
            (<filename>/user/application-root</filename>) should be automatically
            detected by <classname>Zend_Controller_Request_Http</classname> and used
            accordingly.
        </para>

        <para>
            Should the base <acronym>URL</acronym> be detected incorrectly you can override it with
            your own base path by using
            <classname>Zend_Controller_Request_Http</classname> and calling the
            <methodname>setBaseUrl()</methodname> method (see <link
                linkend="zend.controller.request.http.baseurl">Base URL and Subdirectories</link>):
        </para>

        <programlisting language="php"><![CDATA[
$request->setBaseUrl('/~user/application-root/');
]]></programlisting>
    </sect2>

    <sect2 id="zend.controller.router.global.parameters">
        <title>Global Parameters</title>

        <para>
            You can set global parameters in a router which are automatically
            supplied to a route when assembling through
            <methodname>setGlobalParam()</methodname>. If a global parameter is set
            but also given to the assemble method directly, the user parameter
            overrides the global parameter. You can set a global parameter this
            way:
        </para>

        <programlisting language="php"><![CDATA[
$router->setGlobalParam('lang', 'en');
]]></programlisting>
    </sect2>

    <sect2 id="zend.controller.router.routes">
        <title>Route Types</title>
        <xi:include href="Zend_Controller-Router-Route.xml" />
        <xi:include href="Zend_Controller-Router-Route-Static.xml" />
        <xi:include href="Zend_Controller-Router-Route-Regex.xml" />
        <xi:include href="Zend_Controller-Router-Route-Hostname.xml" />
        <xi:include href="Zend_Controller-Router-Route-Chain.xml" />
        <xi:include href="Zend_Controller-Router-Route-Rest.xml" />
    </sect2>

    <sect2 id="zend.controller.router.add-config">
        <title>Using Zend_Config with the RewriteRouter</title>

        <para>
            Sometimes it is more convenient to update a configuration file with
            new routes than to change the code. This is possible via the
            <methodname>addConfig()</methodname> method. Basically, you create a
            <classname>Zend_Config</classname>-compatible configuration, and in your code read it in
            and pass it to the RewriteRouter.
        </para>

        <para>
            As an example, consider the following <acronym>INI</acronym> file:
        </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"
; OR: routes.archive.map.year = 1
]]></programlisting>

        <para>
            The above <acronym>INI</acronym> file can then be read into a
            <classname>Zend_Config</classname> object as follows:
        </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>
            In the above example, we tell the router to use the 'routes' section
            of the <acronym>INI</acronym> file to use for its routes. Each first-level key under
            that section will be used to define a route name; the above example
            defines the routes 'archive' and 'news'. Each route then requires,
            at minimum, a 'route' entry and one or more 'defaults' entries;
            optionally one or more 'reqs' (short for 'required') may be
            provided. All told, these correspond to the three arguments provided
            to a <classname>Zend_Controller_Router_Route_Interface</classname> object. An
            option key, 'type', can be used to specify the route class type to
            use for that particular route; by default, it uses
            <classname>Zend_Controller_Router_Route</classname>. In the example above, the
            'news' route is defined to use
            <classname>Zend_Controller_Router_Route_Static</classname>.
        </para>
    </sect2>

    <sect2 id="zend.controller.router.subclassing">
        <title>Subclassing the Router</title>

        <para>
            The standard rewrite router should provide most functionality you
            may need; most often, you will only need to create a new route type
            in order to provide new or modified functionality over the provided
            routes.
        </para>

        <para>
            That said, you may at some point find yourself wanting to use a
            different routing paradigm. The interface
            <classname>Zend_Controller_Router_Interface</classname> provides the minimal
            information required to create a router, and consists of a single
            method.
        </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>
            Routing only occurs once: when the request is first received into
            the system. The purpose of the router is to determine the
            controller, action, and optional parameters based on the request
            environment, and then set them in the request. The request object
            is then passed to the dispatcher. If it is not possible to map a
            route to a dispatch token, the router should do nothing to the
            request object.
        </para>
    </sect2>
</sect1>
<!--
vim:se ts=4 sw=4 et:
-->