13

I've defined a route in my app routing file:

RouteName:
    pattern:  /some/route
    defaults: { _controller: MyAppBundle:Controller:action }

In a controller I can use:

$this->get('router')->generate('RouteName');

How would I simply access that from a fresh class I create, for example a view class that doesn't extend anything:

namespace My\AppBundle\View;

class ViewClass {
    public function uri()
    {
        return getTheRoute('RouteName');
    }
}
  • Can you explain more about the `ViewClass` you are creating? What is the connection between `ViewClass` and template? – Mun Mun Das Sep 14 '12 at 22:32

4 Answers4

36

You need to inject "router" service into your ViewClass. Eg. in place where your define your ViewClass service:

viewclass.service:
    class: Namespace\For\ViewClass
    arguments:
       router: "@router"

and then in your constructor:

public function __construct(\Symfony\Bundle\FrameworkBundle\Routing\Router $router)
{
    $this->router = $router;
}
Cyprian
  • 11,174
  • 1
  • 48
  • 45
  • I'm not sure I really understand this - so I would have to pass through the router wherever I call VewClass? `new ViewClass(new Router())` ? –  Sep 17 '12 at 15:03
  • 1
    Not exactly. Because wherever in your project you need instance of ViewClass, you'll get one via Dependency Injection Container. For example if you define ViewClass service as in my answer, in your controller you get it in this way: $viewClass = $this->get('viewclass.service') and you don't care about creating new object by yourself. Defining it in service.yml is enough – Cyprian Sep 17 '12 at 16:08
  • beware of the \Symfony\Cmf\Component\Routing\ChainRouter that is a class not in syumfony full stack but in symfony CMF – Bruno Jan 03 '17 at 16:42
  • @bruno Someone edited my original answer and added this "ChainRouter" part, don't know why that passed reviews... (http://stackoverflow.com/posts/12372016/revisions) I'll edit this to original form. – Cyprian Jan 04 '17 at 11:06
1

The clue is in how the $this->generateUrl() method works in Controllers. See:

/**
 * Generates a URL from the given parameters.
 *
 * @param string  $route      The name of the route
 * @param mixed   $parameters An array of parameters
 * @param Boolean $absolute   Whether to generate an absolute URL
 *
 * @return string The generated URL
 */
public function generateUrl($route, $parameters = array(), $absolute = false)
{
    return $this->container->get('router')->generate($route, $parameters, $absolute);
}

So you'll need to define your class as a service and inject the @router service. Either that or have your class implement ContainerAwareInterface, but the first method would definitely be better.

RobMasters
  • 4,108
  • 2
  • 27
  • 34
  • I'm not sure creating a service is the best thing for me, as I am creating a ViewClass for each view of my site (a lot). Therefore each ViewClass is normally only going to be used in one place only, and hence not really a service. Can you give a bit more info on implementing ContainerAwareInterface. Is that the only class I need to load? –  Sep 11 '12 at 14:41
  • Actually I think you'll still need to define the class as a service in order to make use of the ContainerAwareInterface. All this would do is automatically call `setContainer` on your class before providing it, thus allowing you to access any service in the container. You shouldn't be apprehensive about creating a service, it's a very cheap operation. – RobMasters Sep 11 '12 at 15:05
1

You should register your class as a service and insert the router as a dependency.

See the chapter on the service container in the excellent symfony2 docs.

If you're not familiar with the concepts of the service container and dependency injection, you might feel a bit overwhelmed. However, try your best to understand it because it is a essential part of the symfony2 architecture.

Thomas K
  • 6,076
  • 5
  • 39
  • 56
0

You could pass the entire container from your controller to your view class on instantiation. This is NOT BEST PRACTICE and not recommended.

class View
{
  protected $container;

  public function __construct(\Symfony\Component\DependencyInjection\Container $container)
  {
    $this->container = $container;
  }
}

Then in your code you could use

$this->container->get('router')->generate($route, $parameters, $absolute);
james_t
  • 2,723
  • 1
  • 15
  • 20
  • 4
    Why would you suggest this if it isn't best practice? – theunraveler Sep 14 '12 at 17:35
  • It answers the question, it's not the way you should do it, but it is the way the OP would need to do it to keep with the pattern described in his question. – james_t Sep 14 '12 at 19:35