📜 ⬆️ ⬇️

Symfony2 Routing. What's new?

Recently released symfony 2 preview release. I want to tell what changes the routing system underwent in the second branch of the framework.


So, let's begin.

In the article, I do not describe how routing in symfony works. You can read about it here or see the code ! Next I will describe what has changed in the second branch of the framework.
')

What's new?


  1. The routing system has been moved to components ; now it can be used separately from the framework.
  2. It goes without saying that the code has been reworked and performance has been improved. An object is no longer created for every routing rule (unless of course caching is used!).
  3. When comparing the route and url'a. First, the strpos function is used (when it is possible), and then only preg_match.
  4. Different objects (ProjectUrlGenerator, ProjectUrlMatcher) are engaged in the generation of urls and their comparison.
  5. Any class of routing system can now be replaced by passing the appropriate parameters to the constructor of the class Symfony \ Components \ Routing \ Router.
  6. In addition to the dump rules in php, there is a dumper for Apache. I think you can write and dumper files for nginx, if desired.


What is not?


  1. Removed (or maybe not done yet) the possibility of using stars in patterns. The rule "/: module /: action / *" will not work as before.


Below I provide code sections illustrating the new). Routing I tested separately from the framework, so that the data in the rules are different, but the essence remains the same. Namely, the $ defaults array is different. Instead of the _bundle, _controller, _action parameters, I made a module, an action.

An example of a rule dump in symfony 1.2:


<?php
// auto-generated by sfRoutingConfigHandler
// date: 2010/03/14 00:46:57
return array(
'addTopic' => new sfRoute( 'blogs/add-topic/' , array (
'module' => 'blogsEdit' ,
'action' => 'addTopic' ,
), array (), array ()),
'editTopic' => new sfRoute( 'blogs/edit-topic/:id/' , array (
'module' => 'blogsEdit' ,
'action' => 'editTopic' ,
), array (), array ()),
'themeBlog' => new sfRoute( 'blogs/:name/' , array (
'module' => 'blogs' ,
'action' => 'blog' ,
), array (), array ())
// .. ..
);


* This source code was highlighted with Source Code Highlighter .

An example of a rule dump in symfony 1.4:


<?php
// auto-generated by sfRoutingConfigHandler
// date: 2010/03/14 00:46:57

$ this ->routes[ 'route-1' ] = unserialize( ' ' );
$ this ->routes[ 'route-2' ] = unserialize( ' ' );
$ this ->routes[ 'route-6' ] = unserialize( ' ' );
$ this ->routes[ 'route-7' ] = unserialize( ' ' );
$ this ->routes[ 'route-8' ] = unserialize( ' ' );
$ this ->routes[ 'route-9' ] = unserialize( ' ' );
$ this ->routes[ 'route-10' ] = unserialize( ' ' );
$ this ->routes[ 'route-11' ] = unserialize( ' ' );
$ this ->routes[ 'route-12' ] = unserialize( ' ' );

$ this ->routes[ 'homepage' ] = unserialize( ' ' );
$ this ->routes[ 'default_index' ] = unserialize( ' ' );
$ this ->routes[ 'default' ] = unserialize( ' ' );

* This source code was highlighted with Source Code Highlighter .


An example of routing rules in symfony 2:


# blog
addTopic:
pattern: blogs/add-topic/
defaults: { module: blogsEdit, action: addTopic }

editTopic:
pattern: blogs/edit-topic/:id/
defaults: { module: blogsEdit, action: editTopic }

themeBlog:
pattern: blogs/:name/
defaults: { module: blogs, action: blog }


* This source code was highlighted with Source Code Highlighter .


An example of the ProjectUrlMatcher class in Symfony 2:


<?php

/**
* ProjectUrlMatcher
*
* This class has been auto-generated
* by the Symfony Routing Component.
*/
class ProjectUrlMatcher extends Symfony\\Components\\Routing\\Matcher\\UrlMatcher
{
/**
* Constructor.
*/
public function __construct(array $context = array(), array $defaults = array())
{
$ this ->context = $context;
$ this ->defaults = $defaults;
}

public function match($url)
{
$url = $ this ->normalizeUrl($url);

if (0 === strpos($url, '/blogs/add-topic' ) && preg_match( '#^/blogs/add\-topic$#x' , $url, $matches))
return array_merge($ this ->mergeDefaults($matches, array ( 'module' => 'blogsEdit' , 'action' => 'addTopic' ,)), array( '_route' => 'addTopic' ));

if (0 === strpos($url, '/blogs/edit-topic' ) && preg_match( '#^/blogs/edit\-topic/(?P<id>[^/\.]+?)$#x' , $url, $matches))
return array_merge($ this ->mergeDefaults($matches, array ( 'module' => 'blogsEdit' , 'action' => 'editTopic' ,)), array( '_route' => 'editTopic' ));

if (0 === strpos($url, '/blogs' ) && preg_match( '#^/blogs/(?P<name>[^/\.]+?)$#x' , $url, $matches))
return array_merge($ this ->mergeDefaults($matches, array ( 'module' => 'blogs' , 'action' => 'blog' ,)), array( '_route' => 'themeBlog' ));

// ..

return false ;
}
}

* This source code was highlighted with Source Code Highlighter .


Example class ProjectUrlGenerator Symfony 2:


<?php

/**
* ProjectUrlGenerator
*
* This class has been auto-generated
* by the Symfony Routing Component.
*/
class ProjectUrlGenerator extends Symfony\\Components\\Routing\\Generator\\UrlGenerator
{
/**
* Constructor.
*/
public function __construct(array $context = array(), array $defaults = array())
{
$ this ->context = $context;
$ this ->defaults = $defaults;
}

public function generate($name, array $parameters, $absolute = false )
{
if (!method_exists($ this , $method = 'get' .$name. 'RouteInfo' ))
{
throw new InvalidArgumentException(sprintf( 'Route "%s" does not exist.' , $name));
}

list($variables, $defaults, $tokens) = $ this ->$method();

return $ this ->doGenerate($variables, $defaults, $tokens, $parameters, $name, $absolute);
}

protected function getaddTopicRouteInfo()
{
return array(array (), array_merge($ this ->defaults, array ( 'module' => 'blogsEdit' , 'action' => 'addTopic' ,)), array ( 0 => array ( 0 => 'text' , 1 => '/' , 2 => '' , 3 => NULL, ), 1 => array ( 0 => 'text' , 1 => '/' , 2 => 'add-topic' , 3 => NULL, ), 2 => array ( 0 => 'text' , 1 => '/' , 2 => 'blogs' , 3 => NULL, ),));
}

protected function geteditTopicRouteInfo()
{
return array(array ( 'id' => ':id' ,), array_merge($ this ->defaults, array ( 'module' => 'blogsEdit' , 'action' => 'editTopic' ,)), array ( 0 => array ( 0 => 'text' , 1 => '/' , 2 => '' , 3 => NULL, ), 1 => array ( 0 => 'variable' , 1 => '/' , 2 => ':id' , 3 => 'id' , ), 2 => array ( 0 => 'text' , 1 => '/' , 2 => 'edit-topic' , 3 => NULL, ), 3 => array ( 0 => 'text' , 1 => '/' , 2 => 'blogs' , 3 => NULL, ),));
}

protected function getthemeBlogRouteInfo()
{
return array(array ( 'name' => ':name' ,), array_merge($ this ->defaults, array ( 'module' => 'blogs' , 'action' => 'blog' ,)), array ( 0 => array ( 0 => 'text' , 1 => '/' , 2 => '' , 3 => NULL, ), 1 => array ( 0 => 'variable' , 1 => '/' , 2 => ':name' , 3 => 'name' , ), 2 => array ( 0 => 'text' , 1 => '/' , 2 => 'blogs' , 3 => NULL, ),));
}
}

* This source code was highlighted with Source Code Highlighter .


An example of a rule dump for apache in symfony 2:


RewriteCond %{PATH_INFO} ^/blogs/add\-topic/$
RewriteRule .* index.php [QSA,L,E=_ROUTING__route:addTopic,E=_ROUTING_module:blogsEdit,E=_ROUTING_action:addTopic]

RewriteCond %{PATH_INFO} ^/blogs/edit\-topic/([^/\.]+?)/$
RewriteRule .* index.php [QSA,L,E=_ROUTING__route:editTopic,E=_ROUTING_id:%1,E=_ROUTING_module:blogsEdit,E=_ROUTING_action:editTopic]

RewriteCond %{PATH_INFO} ^/blogs/([^/\.]+?)/([^/\.]+?)/$
RewriteRule .* index.php [QSA,L,E=_ROUTING__route:topicInThemeBlog,E=_ROUTING_name:%1,E=_ROUTING_id:%2,E=_ROUTING_module:blogs,E=_ROUTING_action:topic]

* This source code was highlighted with Source Code Highlighter .


Conclusion:
In the second branch of symfony, the routing system is completely rewritten. I used to consider it cumbersome. Now I take my words back. It's nice that the developers optimized the generated files and made it possible to dump the rules in apache. The fact that the routing system can be used separately from the framework is definitely a plus! As for me, such components improve the life of a developer!

Source: https://habr.com/ru/post/87511/


All Articles