Skip to end of metadata
Go to start of metadata

<h1>Zend_Controller_Router 2.0 RoadMap</h1>

<ac:macro ac:name="toc-zone"><ac:parameter ac:name="type">list</ac:parameter><ac:parameter ac:name="minLevel">2</ac:parameter><ac:parameter ac:name="maxLevel">3</ac:parameter><ac:parameter ac:name="location">top</ac:parameter></ac:macro>

<h2>Refactoring of Zend_Controller_Router_Rewrite</h2>

<h3>Goal</h3>

<p>The current layout of the router and it's routes is not very flexible and was not made for the problems it currently tries to solve. Thus, it is going under refactoring to solve the drawbacks. In general, the following topics should be covered with the new router:</p>

<ul>
<li>Lightweight: Should be as fast or if possible even faster than the current implementation</li>
<li>Design by contract: The router and its routes get covered by interfaces</li>
<li>The router should completly work with the request object instead of URL-strings</li>
<li>Fixing bugs which are hard to fix without a BC-break</li>
</ul>

<h3>Routes</h3>

<p>Routes are something which are independent to the rewrite router, and thus can be interfaced completly for this purpose:</p>

<ul>
<li>The getInstance() method will be removed from all routes. Instead we will use a unified constructor</li>
<li>getDefault() and getDefaults() will become interface methods</li>
<li>The match() method will only allow an instance of Zend\Controller\Request\Http</li>
</ul>

<h4>Building routes via config</h4>

<p>The router will allow to not only give complete class names for the route types, but also just the actual route name (module, regex, chain, etc.). This allows for much less typing-work. The router will also accept arrays as configuration now instead of just Zend_Config instances (see unified constructors).</p>

<h4>Chaining</h4>

<p>The currently known chaining will be dropped in favor of tree-matching. This will be setup similar to route chaining, but allow to match a segment in the tree only once, which will lead to better performance. For instance the router will only have to check for the hostname only once, instead of the current approach matching it for every single route again and again.</p>

<h4>Hostname route</h4>

<p>The hostname route will get an additional parameter, which will allow to enforce https connections. If activated, the route will only match when the connections comes via HTTPS, and assembling will prefix https:// instead of http://.</p>

<h3>Caching support</h3>

<p>The new rewrite router system will also come with caching support. This will be supported by creating a unique key out of the HTTP request object and storing the matched result. By doing this, a specific route will only have to be matched once. This allows future matching of the same route without iterating through all defined routes. </p>

<h3>Interfaces</h3>

<ul>
<li>Zend\Controller\Router\RouterInterface</li>
<li>Zend\Controller\Router\Rewrite\RouteInterface</li>
</ul>

<h3>Abstract</h3>

<ul>
<li>Zend\Controller\Router\RouterAbstract</li>
</ul>

<h3>Classes</h3>

<ul>
<li>Zend\Controller\Router\Rewrite\Router</li>
<li>Zend\Controller\Router\Rewrite\Route\Module</li>
<li>Zend\Controller\Router\Rewrite\Route\Segment</li>
<li>Zend\Controller\Router\Rewrite\Route\Chain</li>
<li>Zend\Controller\Router\Rewrite\Route\Regex</li>
</ul>

<h3>CS-Cleanup</h3>

<p>Currently the router doesn't follow the coding standard completly, this will be solved together with the refactoring.</p>

<h3>Prototype</h3>

<p>There is also a protoype unter development. Currently there's not much to see, but it will evolve in the near future:</p>

<p><a class="external-link" href="http://framework.zend.com/svn/framework/standard/branches/user/dasprid/Zend_Controller_Router-2.0/">http://framework.zend.com/svn/framework/standard/branches/user/dasprid/Zend_Controller_Router-2.0/</a></p>

<h2><a href="http://framework.zend.com/issues/secure/IssueNavigator.jspa?reset=true&jqlQuery=project+%3D+ZF+AND+%28summary+router+OR+descriptionrouter%29+AND+resolution%3D+Unresolved+AND+fixVersion+%3D+EMPTY+AND+component+%3D+Zend_Controller+ORDER+BY+priority+DESC">Open JIRA Issues</a></h2>

<ac:macro ac:name="jiraissues"><ac:parameter ac:name="columns">key;type;priority;summary;created;updated</ac:parameter><ac:parameter ac:name="url">http://framework.zend.com/issues/secure/IssueNavigator.jspa?view=rss&amp;jqlQuery=project+%3D+ZF+AND+%28summary+~+router+OR+description+~+router%29+AND+resolution+%3D+Unresolved+AND+fixVersion+%3D+EMPTY+AND+component+%3D+Zend_Controller+ORDER+BY+priority+DESC&amp;tempMax=1000</ac:parameter><ac:parameter ac:name="cache">off</ac:parameter></ac:macro>

Labels:
None
Enter labels to add to this page:
Please wait 
Looking for a label? Just start typing.
  1. Nov 13, 2009

    <p>It has been said that the new Mvc implementation will require explicit definition of the routes because this way nothing has to be autodiscovered. How this affects the router? What will have to be added during an application transition to 2.0?</p>

    1. Nov 17, 2009

      <p>We may have multiple router implementations. The current router is incredibly flexible, and provides a ton of features while simultaneously being incredibly fast. That said, having a way to map routes to specific controllers would be very helpful in many situations, and also solve the dispatcher bottleneck. Having the flexibility to choose approach is what we want to offer.</p>

  2. Nov 13, 2009

    <ul>
    <li>The router should completly work with the request object instead of URL-strings</li>
    </ul>

    <p>Great idea <ac:emoticon ac:name="smile" /></p>

  3. Nov 13, 2009

    <p>I was planning on submitting this as a proposal, but never got round to it, so I guess now is as good time as any.</p>

    <p>I think there is much greater room for defining the standard route parser, allowing for the current :param1/:param2 syntax, whilst allowing greater flexibility.</p>

    <p>Basically, the route string could be parsed before-hand to allow such things as optional parameters and literals inside the same url part, e.g.<br />
     :param1

    Unknown macro: {/}

    /:param3.html<br />
    {} being optional</p>

    <p>I've already written my own route class which does this, and translates both ways giving the exact same result both matching and assembling:</p>

    <p><a href="https://svn.webtatic.com/framework/trunk/library/Webtatic/Controller/Router/Route.php">https://svn.webtatic.com/framework/trunk/library/Webtatic/Controller/Router/Route.php</a></p>

    <p>Ignoring my implementation, which I use my own parser class, would something like this be possible?
    <br class="atl-forced-newline" /></p>

    <p>Aside from this, it at the moment allows enfocement of trailing / in urls if the last part of the route string is /.</p>

    <p>However I was also wondering about the possibility for http redirects, so that :param1/:param2/, would redirect part1/part2 to part1/part2/</p>

    <p>This would be so that it is more SEO friendly (only having one obvious url) </p>

    1. Nov 13, 2009

      <p>I should also add, as I guess this will come up</p>

      <p>If you believe the parsing to be a performance hit, this could be a non-standard route class.</p>

      <p>Caching the results of the parser or the instanciated route between requests would significantly reduce any performance loss, and it would be in theory as fast as the Regex route for matching</p>

      1. Nov 13, 2009

        <p>You could do the trailing slash thingy either via a front controller plugin or via mod_rewrite. By the way, Google doesn't care wether a URL ends with a slash or not, it's the same for it.</p>

        1. Nov 15, 2009

          <p>Google would care if many websites were linking to two different urls (one with and one without slash).</p>

          <p>Typically, the Page Rank might split between the urls, for google will see them as two different pages.</p>

          <p>I'm currently doing it via mod_rewrite to redirect non-slashes that have no "extension" in to have the slash, but was thinking its a routing issue really.</p>

          <p>Apache redirects physical directories without / to have them, but that's context sensitive. If there was a file (with no extension) instead, it wouldn't do the redirect.</p>

          <p>mod_rewrite would obviously be the better option performance-wise though.</p>

          1. Nov 18, 2009

            <p>You are actually correct; Still, it is is no job for the router to do some kind of redirections to fix URLs.</p>

  4. Nov 13, 2009

    <p>Some time ago I've written a router using a tree to match requests. In theory, the same effect should be achievable with the current chain router but it requires the developer to think about it instead of letting the framework do the work.</p>

    <p>The goal is that every part is (hopefully) matched only once (multiple times on fallback, e.g. variable route parts). My local testing showed some (more or less) great performance increase.</p>

    1. Nov 13, 2009

      <p>It was also in my mind to change the chaining to a tree-structure-like thing to increase performance, this will probably also be done in 2.0.</p>

    2. Nov 17, 2009

      <p>I've added the proposal for the tree-like routing today and will include it into the prototype.</p>

  5. Mar 18, 2010

    <ul>
    <li>The match() method will only allow an instance of Zend\Controller\Request\Http</li>
    </ul>

    <p>Why the router should only handle HTTP requests ?</p>

    <p>I think we can specify a HTTP limit by an additional Interface:</p>
    <ul>
    <li>Zend\Controller\Router\Routable::match(Zend\Controller\Request $rq)</li>
    <li>Zend\Controller\Router\Http\Routable::match(Zend\Controller\Request $rq)
    <ul>
    <li>throws an InvalidArgumentException if $rq isn't an instance of Zend\Controller\Request\Http</li>
    </ul>
    </li>
    <li>Zend\Controller\Router\Http\Rewrite implements Zend\Controller\Router\Http\Routable</li>
    </ul>

    <p>Than we can create specific routers for other requests. Example for CLI:</p>
    <ul>
    <li>Zend\Controller\Router\Cli\Routable::match(Zend\Controller\Request $rq)
    <ul>
    <li>throws an InvalidArgumentException if $rq isn't an instance of Zend\Controller\Request\Cli</li>
    </ul>
    </li>
    <li>Zend\Controller\Router\Cli\Rewrite implements Zend\Controller\Router\Cli\Routable</li>
    </ul>

    1. Mar 18, 2010

      <p>That is specific to the rewrite router. This one will only handle HTTP requests.</p>

      1. Mar 19, 2010

        <p>Ah ok, and the interface will allow an instance of the base request ?</p>

        <p>In my opinion the name "rewrite" is very general and should not limited to HTTP requests. I know a different request is not handleable by one rewrite router. This is why I would like to rename it to make it clear to limit it to HTTP requests.</p>