Skip to end of metadata
Go to start of metadata

<ac:macro ac:name="unmigrated-inline-wiki-markup"><ac:plain-text-body><![CDATA[

<ac:macro ac:name="unmigrated-inline-wiki-markup"><ac:plain-text-body><![CDATA[

Zend Framework: Zend_Controller_Router_RegexRoute Component Proposal

Proposed Component Name Zend_Controller_Router_RegexRoute
Developer Notes
Proposers Micha? Minicki
Revision 1.0 - 23 January 2007: Initial version (wiki revision: 16)

Table of Contents

1. Overview

This new route class allows for defining routes in pure regular expressions without any constraints. It allows to create recursive, look
ahead, conditional patterns. You name it. And should I mention it's fast? Or at least should be considerably faster than the current standard route.

2. References

No references at this point

3. Component Requirements, Constraints, and Acceptance Criteria

No requirements at this point. The class tightly integrates with current framework modules.

4. Dependencies on Other Framework Components

  • Zend_Controller_RewriteRouter

5. Theory of Operation

This Route class is similar in nature to the rest of route classes. It allows mapping of path_info to request parameters.

Regex (first parameter) and defaults (second) are compatible with all other route objects
with one exception - you are be able to define integer indexed defaults in
order to enable it to work with regex subpatterns.

There is a third optional parameter named $map, which holds key-value
pairs for mapping subpatterns to named parameters.

6. Milestones / Tasks

  • Milestone 1: [DONE] Working prototype
  • Milestone 2: [DONE] Unit tests exist and work.
  • Milestone 3: Initial documentation exists.

7. Class Index

  • Zend_Controller_Router_RegexRoute

8. Use Cases

UC-01 Simple match

This creates a route which will match URL of: /articles/2006

Note - regex is automatically surrounded by start, end and delimiter symbols ('#^' . $regex . '$#')

UC-02 Simple match with map

This will match: /articles/2006/page/3. And additionaly it will map catched subpatterns so after matching these will be available through getParam as 'page' and 'aid' (in addition to controller and action).

UC-03 Numeric defaults

This will match:

On the first type of match, parameter indexed with an integer '1' will hold the value of '2006'. Second and third example will hold '2004' and '2007' respectively. The numeric index is an id of regex subpattern position.

UC-04 Mapped mixed defaults

Example URI: /archive

On match this will return 'year' => '2006' and 'month' => '4'. Even though month default is indexed numerically.

9. Class Skeletons



Enter labels to add to this page:
Please wait 
Looking for a label? Just start typing.
  1. Jan 24, 2007

    <p>Great idea!</p>

    <p>It would be useful if the documentation were to include examples of useful regexp's.</p>

    <p>Example: won't UC-03 also match /articles2007, which would probably not be desirable.</p>

    1. Jan 25, 2007

      <p>I have given this example to make regex a little bit more readable (and as such easier to understand). The correct way to do that would probably be:</p>

      <ac:macro ac:name="code"><ac:plain-text-body><![CDATA[
      new RegexRoute('^/archive(?:/(\d+))?',
      array('controller' => 'archive', 'action' => 'show', 1 => '2006'),

      <p>Same goes with fourth.</p>

      <p>Thanks for pointing that out, Richard.</p>

  2. Feb 02, 2007

    <p>I find this approach quite intuitive and even more comfortable than others, since I've worked with REs for so many years <ac:emoticon ac:name="smile" /></p>

    <p>I would suggest also including support (and use cases) for debugging and testing these routes. With REs, the most time consuming task usually becomes debugging tiny flaws in RE patterns. If there is an extremely simple API to specify a list of test cases and expected results for each of several different inputs, then I would find this component even more useful. PHPUnit tests would suffice, but perhaps we can be more creative with some sort of value add for this specific situation (testing routes)? For example, a debug option that logs input URL, matched routes, and matched params might simplify diagnosing problems.</p>

    1. Feb 03, 2007

      <p>Debug option sounds great. But I would go even further and implement it at the RewriteRouter level to work with any type of Route. This would be a great opportunity to use emerging Zend_Log after it gets approved to the incubator:</p>

      <ac:macro ac:name="code"><ac:plain-text-body><![CDATA[
      public function setDebug(Zend_Log $log) {
      $this->_log = $log;

      public function match() {


      foreach ($this->_routes as $route) {


      if ($this->_log)

      Unknown macro: { $message = 'Type}


      <p>And this actually gave me an idea for the Zend_Log. I will post it in their proposal in a minute:</p>

      <ac:macro ac:name="code"><ac:plain-text-body><![CDATA[
      $message = array(
      'Type' => get_class($route),
      'Route' => $route->getMatchString(),
      'Path' => $path,
      'Result' => $result

      1. Feb 03, 2007

        <p>Feature request added:
        <a class="external-link" href=""></a></p>

  3. Feb 02, 2007

    <p>This would be a fine addition to the family of routers.</p>

    <p>I have another use case to complicate things:</p>
    <ac:macro ac:name="code"><ac:plain-text-body><![CDATA[
    new RegexRoute('/articles/(\d+)(?:#(.*))',
    array('controller' => 'article', 'action' => 'archive'),
    array(1 => 'year', 2 => 'anchor')

    <p>The goals is for the optional anchor text following '#' in the URL to be available as a parameter to the controller.</p>

    <p>The problem is that you're using '#' as your regular expression delimiter, so the parsing of the rexpr will be complicated.</p>

    1. Feb 03, 2007

      <p>Actually this won't work - that's why the delimiter is set to this character exactly. </p>

      <p>First of all it would be too tempting to use anchor text to make a decision on which page to route to. And it wouldn't be good since the anchor text should be used only to find anchors on the exactly same page.</p>

      <p>Secondly, RewriteRouter operates on PATH_INFO which does not contain anchor texts. See for yourself: </p>

      <p><a class="external-link" href="http://test.localhost/articles/2006#header1">http://test.localhost/articles/2006#header1</a></p>

      <ac:macro ac:name="code"><ac:plain-text-body><![CDATA[
      $request = new Zend_Controller_Request_Http();


      /* Result:

      string(14) "/articles/2006"
      string(14) "/articles/2006"
      string(14) "/articles/2006"


  4. Feb 11, 2007

    <p>What's the status of this proposal now? I really like it and would like to see it in the incubator soon...</p>

    1. Feb 12, 2007

      <p>I'm ready to commit for at least two weeks now, Tomas. It's all in the hands of Zend guys now.</p>

      1. Feb 12, 2007

        <p>Could you post the code somewhere, then?</p>

        1. Feb 12, 2007

          <p>Let's just wait a little bit more, Aaron. I bet they are pretty busy with Zend 0.8.0 at the moment. I suppose they will turn their attention to proposals after everything settles down a bit.</p>

  5. Feb 13, 2007

    <ac:macro ac:name="note"><ac:parameter ac:name="title">Zend Comments</ac:parameter><ac:rich-text-body>
    <p>This proposal is approved for implementation, with the class name of Zend_Controller_Router_Route_Regex.</p>

    <p>Please implement in the incubator; however, it may be moved to core as soon as test coverage and documentation are complete.</p></ac:rich-text-body></ac:macro>