Impossible to pass the router service to a twig extension in symfony 2.6

风格不统一 提交于 2019-12-10 09:53:15

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!