在Symfony 2.6中,无法将路由器服务传递给Twig扩展。

3

我有一个twig扩展,我想注入路由器服务,所以... services.yml

app.twig_extension:
    class: SeoReportBundle\Twig\SeoReportExtension
    arguments: [@router]
    tags:
        - { name: twig.extension }

扩展:

使用Symfony\Bundle\FrameworkBundle\Routing\Router;

class SeoReportExtension extends \Twig_Extension
{
    private $router;

    public function __construct(Router $router)
    {
        $this->router = $router;
    }

当我执行代码时,我收到以下错误:

Catchable Fatal Error: Argument 1 passed to SeoReportBundle\Twig\SeoReportExtension::__construct() must be an instance of Symfony\Bundle\FrameworkBundle\Routing\Router, none given

为了尝试调试此问题,我在代码中进行了以下更改以了解情况:

public function __construct($router) {
    var_dump($router);die();
    $this->router = $router; }

所以我移除了类型提示,并在构造方法中转储对象以查看其内容。令我惊讶的是,输出如下:

Object(Symfony\Bundle\FrameworkBundle\Routing\Router)[198]
private 'container' => 
object(appDevDebugProjectContainer)[219]
private 'parameters' => ...

所以...它实际上传递了一个路由器对象。那么...为什么我会得到错误?我在这一点上完全迷失了。

--- 更新 --- 这是我目前找到的: - 在/app/cache/dev/appDevDebugProjectContainer.php中,有两个地方创建了该扩展:

protected function getApp_TwigExtensionService()
    {
        return $this->services['app.twig_extension'] = new \SeoReportBundle\Twig\SeoReportExtension($this->get('router'));
    }

哪个是正确的,它将路由器传递给构造函数 以及...
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());

现在,这个扩展程序不能通过路由器。但是它确实传递了一些依赖关系给其他扩展程序。所以一定有某种原因导致我的扩展程序无法运作。


只是为了好玩,去掉public:false属性。您可以忽略此项,因为文档显示使用public:false。 - Cerad
你可以将容器传递给Twig扩展 http://symfony.com/doc/current/cookbook/service_container/scopes.html#c-passing-the-container-as-a-dependency-of-your-service - Tom
@thom,这完全违背了依赖注入的理念。 - gries
1
好的。你的配置操作有些奇怪。我建议你先下载一个新的Symfony项目,然后添加你的twig扩展并确保它能够正常加载。然后尝试找出差异在哪里。这似乎是你在某个地方使用了编译器传递?或者可能是两个服务都引用了你的类?我假设你在重建时完全删除了缓存目录。 - Cerad
1
我找到了问题所在...我有两个不同配置的services.yml文件,它们导致了问题。谢谢大家的时间 :) - petekaner
显示剩余13条评论
1个回答

0

Twig环境对于\Twig_SimpleFunction实例和\Twig_SimpleFilter同样可用,尽管Twig文档仅显示它用于过滤器。从环境中,您可以像这样获取路由扩展:

/**
 * {@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);
}

在那个$env中还有很多其他好玩的东西 - 值得尝试dump(get_class_methods($env));,然后转储其中任何你感兴趣的内容。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接