2012-01-16 51 views
9

我有2个参数的路线:Symfony2的:使用对象来设置路由参数

BBBundle_blog_show: 
    pattern: /{id}/{slug} 
    defaults: { _controller: BloggerBlogBundle:Blog:show } 
    requirements: 
     _method: GET 
     id: \d+ 

两个PARAMS是对象博客的性质。

我想建立一个自定义映射器(路线发生器),这样我就可以这样写:

{{ path('BBBundle_blog_show', {'blog': blog}) }} 

,而不是这样的:

{{ path('BBBundle_blog_show', {'id':blog.id, 'slug':blog.slug) }} 
+0

我很想看到这个(肯定会清理我的代码位),但据我所知这是不可能的。 – MrGlass 2012-01-16 14:05:04

回答

7

这是我想出了最终:

我通过自己的生成器基类实现,查找'对象'参数并尝试从该对象获取所需的参数。

//src/Blogger/BlogBundle/Resources/config/services.yml 
parameters:  
    router.options.generator_base_class: Blogger\BlogBundle\Routing\Generator\UrlGenerator 
//src/Blogger/BlogBundle/Routing/Generator/UrlGenerator.php 

namespace Blogger\BlogBundle\Routing\Generator; 

use Symfony\Component\Routing\Generator\UrlGenerator as BaseUrlGenerator; 

use Doctrine\Common\Util\Inflector; 

/** 
* UrlGenerator generates URL based on a set of routes. 
* 
* @api 
*/ 
class UrlGenerator extends BaseUrlGenerator 
{ 
    protected function doGenerate($variables, $defaults, $requirements, $tokens, $parameters, $name, $absolute) 
    { 
     if (isset($parameters['object']) && is_object($parameters['object'])) { 
      $object = $parameters['object']; 
      $parameters = array_replace($this->context->getParameters(), $parameters); 
      $tparams = array_replace($defaults, $parameters); 
      $requiredParameters = array_diff_key(array_flip($variables), $tparams); 

      $parameters = $this->getParametersFromObject(array_flip($requiredParameters), $object); 
     } 

     return parent::doGenerate($variables, $defaults, $requirements, $tokens, $parameters, $name, $absolute); 
    } 

    protected function getParametersFromObject($keys, $object) 
    { 
     $parameters = array(); 
     foreach ($keys as $key) { 
      $method = 'get' . Inflector::classify($key); 
      if (method_exists($object, $method)) { 
       $parameters[$key] = $object->$method(); 
      } 
     } 

     return $parameters; 
    } 

} 

现在我可以这样写:从对象,并会得到所需要的参数(ID,蛞蝓):{} {路径(博客} 'BBBundle_blog_show',{ '对象')} 。

+1

你能分享你的路线配置吗? – drupality 2012-01-29 19:09:52

+0

你的意思是routing.yml?这与沙箱项目中的相同。 – Dziamid 2012-01-30 10:42:11

+0

我在这里扩展了这个答案:https://gist.github.com/3226510,你现在可以传递对象而不是数组,即'path('route',entity)'(应该是BC) 。同样,在检查一个匹配键后,路由器将用'_'来爆炸键以检查关系,即'parent_slug'将解析为'$ object-> getParent() - > getSlug()'。 – Steve 2012-08-01 12:47:13

0

前段时间,我决定让我感到恼火,因为无法传递对象作为路由参数。我不得不关注路线知识以及模板中的确切参数值以及其他生成这些路线的事情。

我已经为symfony构建了这个包,它允许你使用和扩展这个能力(Symfony 2.7和更高版本)。请看看:https://github.com/iltar/http-bundle。它也可以在Packagist上作为iltar/http-bundle使用。

这个包最好的事情是你不需要使用另一个路由器对象或生成器。它只是打开捆绑包,根据需要调整配置,如果默认设置不适合您的偏好,那么您就可以走了。自述应该解释一切,你需要知道,但这里有一个片段:

旧风格:

/** 
* @Route("/profile/{user}/", name="app.view-profile") 
*/ 
public function viewProfileAction(AppUser $user); 

// php 
$router->generate('app.view-profile', ['user' => $user->getId()]); 

// twig 
{{ path('app.view-profile', { 'user': user.id }) }} 
{{ path('app.view-profile', { 'user': user.getid }) }} 
{{ path('app.view-profile', { 'user': user.getId() }) }} 
{{ path('app.view-profile', { 'user': user[id] }) }} 

新风格:

// php 
$router->generate('app.view-profile', ['user' => $user]); 

// twig 
{{ path('app.view-profile', { 'user' : user }) }}