问题
I have a twig extension where I'm trying to inject the router service, so... services.yml
app.twig_extension:
class: SeoReportBundle\Twig\SeoReportExtension
arguments: [@router]
tags:
- { name: twig.extension }
Extension:
use Symfony\Bundle\FrameworkBundle\Routing\Router;
class SeoReportExtension extends \Twig_Extension
{
private $router;
public function __construct(Router $router)
{
$this->router = $router;
}
When I execute the code I get this error:
Catchable Fatal Error: Argument 1 passed to SeoReportBundle\Twig\SeoReportExtension::__construct() must be an instance of Symfony\Bundle\FrameworkBundle\Routing\Router, none given
Trying to debug this, I did this change in the code to try to understand what's going on:
public function __construct($router) {
var_dump($router);die();
$this->router = $router; }
So I remove the type hint and I do a dump of the object to see what's getting in the construct method. To my surprise, this is the output:
Object(Symfony\Bundle\FrameworkBundle\Routing\Router)[198]
private 'container' =>
object(appDevDebugProjectContainer)[219]
private 'parameters' => ...
So... it actually passes a router object. So... why am I getting the error? I completely lost at this point
--- UPDATE --- Here's what I found so far: - In /app/cache/dev/appDevDebugProjectContainer.php there are two places where the extension is created:
protected function getApp_TwigExtensionService()
{
return $this->services['app.twig_extension'] = new \SeoReportBundle\Twig\SeoReportExtension($this->get('router'));
}
Which is correct, it passes the router to the construct And...
protected function getTwigService()
{
$this->services['twig'] = $instance = new \Twig_Environment($this->get('twig.loader'), array('debug' => true, 'strict_variables' => true, 'exception_controller' => 'twig.controller.exception:showAction', 'form_themes' => array(0 => 'form_div_layout.html.twig'), 'autoescape' => array(0 => 'Symfony\\Bundle\\TwigBundle\\TwigDefaultEscapingStrategy', 1 => 'guess'), 'cache' => (__DIR__.'/twig'), 'charset' => 'UTF-8', 'paths' => array()));
$instance->addExtension($this->get('app.twig_extension'));
...
$instance->addExtension(new \Symfony\Bundle\AsseticBundle\Twig\AsseticExtension($this->get('assetic.asset_factory'), $this->get('templating.name_parser'), true, array(), array(0 => 'SeoReportBundle'), new \Symfony\Bundle\AsseticBundle\DefaultValueSupplier($this)));
$instance->addExtension(new \Doctrine\Bundle\DoctrineBundle\Twig\DoctrineExtension());
$instance->addExtension(new \SeoReportBundle\Twig\SeoReportExtension());
Now, this one doesn't pass the router. But it does pass some dependencies to other extensions. So there has to be a reason why mine extension is not working
回答1:
The Twig environment is available to \Twig_SimpleFunction
instances as well as \Twig_SimpleFilter
in the same way, though the Twig docs only show it for filters. From the environment, you can get the routing extension like this:
/**
* {@inheritdoc}
*/
public function getFunctions(): array
{
return array(
new \Twig_SimpleFunction('get_my_link_thing', array($this, 'getMyLinkThing'), array('needs_environment' => true)),
);
}
/**
* Get something with a generated link.
*
* @return string
*/
public function getMyLinkThing(\Twig_Environment $env): string
{
$targetUrl = $env->getExtension('routing')->getPath('my_route_name');
return sprintf('Link is <a href="%s">here</a>!', $targetUrl);
}
There are lots of other nifty things in that $env
- it's worth trying dump(get_class_methods($env));
and then dumping the results of calling anything in there that strikes your fancy.
来源:https://stackoverflow.com/questions/28676551/impossible-to-pass-the-router-service-to-a-twig-extension-in-symfony-2-6