Pull to refresh

Symfony2 Routing. Что новенького?

Symfony *
Недавно вышла Symfony 2 Preview Release. Я хочу рассказать какие изменения претерпела система роутинга во второй ветке фреймворка.


Итак начнем.

В статье я не описываю как работает роутинг в symfony. Об этом можно почитать тут или посмотреть код! Дальше я опишу, что изменилось во второй ветке фреймворка.

Что новенького?


  1. Система роутинга вынесена в компоненты, теперь ее можно использовать отдельно от фреймворка.
  2. Само собой переработан код, повышена производительность. На каждое правило роутинга теперь не создается объект (если конечно используется кэширование!).
  3. При сопоставлении роута и url'a. Сначала используется функция strpos (когда это возможно), а потом только preg_match.
  4. Генерацией url'ов и их сопоставлением занимаются разные объекты (ProjectUrlGenerator, ProjectUrlMatcher).
  5. Любой класс системы роутинга теперь можно заменить, путем передачи соответствующих параметров в конструктор класса Symfony\Components\Routing\Router.
  6. Помимо дампа правил в php, есть дампер для Apache. Думаю можно будет написать и дампер файлов для nginx при желании.


Чего нет?


  1. Убрали (а может еще не сделали) возможность использования звезд в паттернах. Правило "/:module/:action/*" работать как прежде не будет.


Ниже я привожу участки кода иллюстрирующие новенькое ). Роутинг я тестил отдельно от фреймворка, так что данные в правилах отличаются, но суть остается прежней. А именно отличается массив $defaults. Вместо параметров _bundle, _controller, _action, я сделал module, action.

Пример дампа правил в 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.

Пример дампа правил в 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.


Пример правил роутинга в 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.


Пример класса ProjectUrlMatcher в 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.


Пример класса 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.


Пример дампа правил для Apache в 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.


Вывод:
Во второй ветке Symfony система роутинга переписана полностью. Раньше я считал ее громоздкой. Теперь же беру свои слова обратно. Очень приятно, что разработчики оптимизировали генерируемые файлы и сделали возможность дампить правила в apache. То что систему роутинга можно использовать одтельно от фреймворка безусловно плюс! Как по мне такие компоненты улучшают жизнь разработчика!
Tags:
Hubs:
Total votes 42: ↑34 and ↓8 +26
Views 5.7K
Comments Comments 19