Symfony2: use object to set route parameters

前端 未结 2 1606

I have a route with 2 parameters:

BBBundle_blog_show:
    pattern:  /{id}/{slug}
    defaults: { _controller: BloggerBlogBundle:Blog:show }
    requirements:         


        
相关标签:
2条回答
  • 2020-12-09 21:35

    A while ago, I decided I was annoyed by being unable to pass objects as route parameters. I had to concern myself with knowledge of routes and the exact parameter values within templates and other things generating those routes.

    I've build this bundle for symfony, which allows you to use and extend this ability (Symfony 2.7 and higher). Please take a look: https://github.com/iltar/http-bundle. It's also available on Packagist as iltar/http-bundle.

    The best thing about this bundle is that you don't need to use another router object or generator. It's just turning on the bundle, adjusting the config to your needs if the defaults don't work out for your preferences and you're good to go. The readme should explain everything you need to know but here's a snippet:

    Old style:

    /**
     * @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] }) }}
    

    New style:

    // php
    $router->generate('app.view-profile', ['user' => $user]);
    
    // twig
    {{ path('app.view-profile', { 'user' : user }) }}
    
    0 讨论(0)
  • 2020-12-09 21:42

    This is what I came up with eventually:

    I implemented by own generator base class that looks for 'object' parameter and tries to get required parameters from that object.

    //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;
        }
    
    }
    

    Now I can write: {{ path('BBBundle_blog_show', {'object': blog}) }} and it will get required parameters (id, slug) from object.

    0 讨论(0)
提交回复
热议问题