2
votes

Sf2.0, standard blog for example.

Code of routing.yml:

DevBlogBundle_post_show:
 pattern:  /posts/{id}
 defaults: { _controller: "DevBlogBundle:Post:show" }
 requirements:
    _method:  GET
    id: \d+

Standard way i generate url for my post by using:

path('DevBlogBundle_post_show',{'id':post.id})

I use this constrution in all my temlates/layouts, which include posts list. An if i want to change my route for post_show (say... add Slug parameter /posts/{id}.{slug}), i will need to change all my temlates. Instead, i want to generate route by my Post model, something like:

public function getUrl(){
     return $this->generator->generate('DevBlogBundle_post_show',array (...params...));}

Question: How can i get This Generator to my Post model, what i have to "use ..." and how to generate route?

In my templates i want to place:

<a href="{{ post.getUrl() }}" ...>...</a>

Thanks in advance.

2
First of all it's a bad idea to put the getUrl into your model, mainly because the model should be rather stupid and not know about how to generate urls. One way would be to create your own twig extension, which can get called on any object of a specific type (e.g. a post and returns the url. You would do something like {{ post|url }} Have a read about extending twig here: kiwwito.com/article/…Sgoettschkes
I know how to create twig ext. And maybe, you are right. I just try to create somths like RoR "to_param". I'll create one twig ext, which i will use instead standard "path" and "url".ZloyPotroh
In this case you may want to look at the Sluggable bundle. Maybethis is what you are looking for: github.com/l3pp4rd/DoctrineExtensions/blob/master/doc/…Sgoettschkes
I think this is an important question. If my brain is right, in sf1 it was possible to pass the whole object to the routing helper and let symfony extract the parameters. So it would be nice to do something like path('DevBlogBundle_post_show',{'post':post}) or path('DevBlogBundle_post_show',post) and let the helper extract the necessary properties. But as it seems it is not possible... any ideas?room13

2 Answers

5
votes

Excited by this question and the thoughts in my previous comment i've hacked together a quick proof of concept to achieve what you where asking for. I've implemented a twig function that can be passed an entity and a route name. The function does the following setps to generate the url:

  1. Get the route specified by name
  2. Compile the route
  3. Obtain the routes variables
  4. Loop over variables and try to call the according getters on the entity to build up the parameters array that is required by the UrlGeneratorInterface to generate a routes url
  5. Let symfony's url generator generate the url

However this implies that the routes parameters are named exactly as the properties in the entities, which IMHO is a good practice anyway. The code needs to be places into a twig extension that has the service container reference injected into the container property.

public function generateEntityUrl($entity,$routeName)
{
    $router         = $this->container->get('router');
    $generator      = $router->getGenerator();
    $collection     = $router->getRouteCollection();
    $route          = $collection->get($routeName);
    $compiledRoute  = $route->compile();
    $variables      = $compiledRoute->getVariables();
    $parameters     = array();

    foreach($variables as $var)
    {
        $getter = 'get'.ucfirst($var);
        $parameters[$var]=$entity->$getter();
    }

    return $generator->generate($routeName,$parameters);

}

In twig you can then call the function with {{post|entity_url('DevBlogBundle_post_show')}}.

But I'm asking myself why there is no implementation yet in symfony... or why i have not found it yet.

1
votes

Ok... and so far there is still no functionality to pass entity parameters to router. Answer by room13 make sense, but I think to make it easier:

In Twig Templates or Haml (strongly recommend, save your time, it will make you happier: https://github.com/arnaud-lb/MtHamlBundle), etc:

{{ path('route_name', entity.toParam()) }}

And in Entity define function like:

public function toParam(){

  // maybe some logic....

  return array(
    'id' => $this->id,
    'slug' => $this->getSlug(),
    .....other needed params
  );
}

Reason: If your route parameters are new option appeared, just add it in one place in Entity#toParam instead of to find, where is route used, and overwrite all twig templates.