[TYPO3-team-core-v5] TYPO3 v5 Routing

Bastian Waidelich waidelich at network-publishing.de
Mon Jun 16 15:56:55 CEST 2008


Hi there,

as you might have read I'm currently working on a routing mechanism for
TYPO3 v5. As this is a feature which can't be easily replaced once it's 
implemented and used in production environments, I'd be happy to get 
some feedback on the initial ideas. So please take some minutes to read 
this.

Routing for a MVC framework is quite straight forward and relatively 
easy to implement: You simply map parts of the request URL to controller 
and action and transform remaining URL segments to request parameters 
that can be accessed from within the controller.
If you take Zend Framework for instance, a default route could look like 
this:

	$route = new Zend_Controller_Router_Route(
		':module/:controller/:action/*',
		array('module' => 'default')
	);
	$router->addRoute('default', $route);

In this route the first URL segment specifies the module (or context). 
It can be omitted cause it defaults to "default". Second and third 
segments map controller and action. the asterisk * means that more 
segments can follow in the format "key1/value1/key2/value2". Those 
parameters are transformed into additional request parameters.
So the URL "http://www.domain.tld/news/show/id/123" would call the show 
action of the news controller in the default module and 
request->getParam('id') would return "123".

A more specific route could be the following:

	$route = new Zend_Controller_Router_Route(
		'news/:id',
		array(
			'module' => 'default',
			'controller' => 'news',
			'action'     => 'show'
		)
	);
	$router->addRoute('news', $route);

Now the URL "http://www.domain.tld/news/123" would have the same result.

The router iterates through all specified routes in descending order 
until a matching route is found.
Pretty simple, and it works like this in most MVC frameworks out there.

The problem with routing in a CMS is: Almost all requests must be mapped 
to the Page controller.
Additionally some kind of namespace is required for parameters so they 
are distinguishable if you have multiple plugins on one page.

Basically everything RealURL does today! The problem with RealURL
though: it's not very intuitive to configure.

So we came up with the idea to implement a feature we called "sub 
routes". One or more URL segments can map to one sub route. This
makes it possible to route "company/about-us" to a single page. 
Furthermore new plugins can add their default sub routes like 
"news/list", "news/archive"...

This would be compatible with the established routing mechanisms. So 
"static" routes could be configured like this:

	/**
	 * default TYPO3 admin route
	 */
	$c->routes->admin
		->setUrlPattern('typo3')
		->setDefaults(
			array(
				'package' => 'TYPO3',
				'controller' => 'Backend',
				'action' => 'default',
			)
		);

This would map the URL "http://www.domain.tld/typo3" to the default 
Action of the Backend controller (in the TYPO3 package).

A default route configuration for the TYPO3 frontend would be a bit more 
complex and could look like this:


	/**
	 * default TYPO3 frontend route
	 */
	$c->routes->default
		->setUrlPattern('[language]/[[page]]/[[pluginOptions]]')
		->setDefaults(
			array(
				'package' => 'TYPO3',
				'controller' => 'Page',
				'action' => 'default',
				'language' => 'en'
			)
		)
		->setRoutePartHandlers(
			array(
				'language' => 'F3_L10N_Routing_ISOResolver',
				'page' => 'F3_TYPO3_Routing_PageResolver',
				'pluginOptions' => 'F3_TYPO3_Routing_PluginResolver'
			)
		);

an URL part in brackets means: this part is dynamic.
an URL part in double brackets means: this part is dynamic and can
consist of more than one URL segment (sub route).
For all dynamic parts a "RoutePartHandler" can be specified. A handler
has to implement some interface and is able to resolve parts of the 
request URL as well as to create URL segments from given data. So it's 
task is comparable to RealURL's valueMap or lookUpTable.

A sub route configuration could be as easy as:

	/**
	 * News details sub route
	 */
	$c->subRoutes->newssingle
		->setUrlPattern('article/[id]');

(to get the news title into the URL instead of an id, a "News title 
resolver" would be possible, but that would go beyond the scope of this 
already rather blown post).

Now one problem remains: to resolve a sub route to a specific plugin, a
keyword is needed. That leads to URLs like 
"http://www.domain.tld/company/news/arcticle/123" (where "company/news" 
is the page and "article" the keyword for the news single view).

For a first version we can live with that I guess. In the long run
Robert had the great idea to add routing options to the TYPO3 pages. So 
you could override routing for a page in the respective page settings.


Now your part:
- Do you think, the concept is understandable?
- What about the configuration format (Do you like the brackets *g)?
- What else? Any ideas, brickbats..?


best regards,
Bastian


More information about the TYPO3-team-core-v5 mailing list