Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Symfony2: use object to set route parameters

Tags:

symfony

I have a route with 2 parameters:

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

Both params are properties of an object blog.

I would like to set up a custom mapper (route generator), so that I can write this:

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

instead of this:

 {{ path('BBBundle_blog_show', {'id':blog.id, 'slug':blog.slug) }}
like image 837
Dziamid Avatar asked Jan 16 '12 09:01

Dziamid


1 Answers

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.

like image 92
Dziamid Avatar answered Oct 21 '22 18:10

Dziamid