【问题标题】:Class does not exist when using service inside compiler pass在编译器传递中使用服务时类不存在
【发布时间】:2017-01-02 03:07:30
【问题描述】:

我注意到一些奇怪的行为,甚至可能是 symfony 中的错误?我不知道...这里是reprocuce的步骤:

1。安装 symfony

​​>

我全新安装了 symfony 3.1.3,使用 cli 安装程序安装:

$ symfony new myproject

2。添加一些服务

我在app/config/services.yml中添加了一个服务定义:

services:
    app.helper:
        class: AppBundle\Service\AppHelper
        arguments: ["@service_container"]

并且我添加了相应的服务类:

<?php
namespace AppBundle\Service;

use Symfony\Component\DependencyInjection\ContainerInterface;

class AppHelper
{
    /**
     * @var ContainerInterface
     */
    private $container;

    /**
     * @var \Doctrine\ORM\EntityManager
     */
    private $em;

    public function __construct(ContainerInterface $container)
    {
        $this->container = $container;
        $this->em = $this->container->get('doctrine.orm.entity_manager');
    }

    /**
     * Returns stuff.
     *
     * @param $key
     * @return mixed
     */
    public function getStuff($key)
    {
        return $this->em->... // get stuff
    }
}

在构造函数中,我注入容器并从中获取理论实体管理器。到目前为止工作正常,例如在控制器内部。

3。添加编译器通道

然后我添加了一个带有空进程方法的编译器类:

<?php
namespace AppBundle\DependencyInjection;


use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\DependencyInjection\ContainerBuilder;

class MenuItemCompilerPass implements CompilerPassInterface
{
    /**
     * Collect modules menu items.
     *
     * @param ContainerBuilder $container
     */
    public function process(ContainerBuilder $container)
    {
    }
}

然后我将它添加到 bundle 类中:

<?php
namespace AppBundle;

use AppBundle\DependencyInjection\MenuItemCompilerPass;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\HttpKernel\Bundle\Bundle;

class AppBundle extends Bundle
{
    public function build(ContainerBuilder $container)
    {
        parent::build($container);

        $container->addCompilerPass(new MenuItemCompilerPass());
    }
}

4。实现失败的代码

现在我想访问MenuItemCompilerPassprocess 方法中的AppHelper 服务:

/**
 * Collect modules menu items.
 *
 * @param ContainerBuilder $container
 */
public function process(ContainerBuilder $container)
{
    $stuff = $container->get('app.helper')->getStuff('something');
}

这会导致以下错误:

ReflectionException in ContainerBuilder.php line 862: Class does not exist

事实证明,当我删除时

$this->em = $this->container->get('doctrine.orm.entity_manager');

AppHelper 中的构造函数再次运行。

谁能说出问题出在哪里?

【问题讨论】:

    标签: php dependency-injection symfony


    【解决方案1】:

    永远不会在编译过程中从容器中获取服务。仅使用定义。

    但是,您可以从容器中获取参数。所以不要做$host = $container-&gt;get('app.helper')-&gt;getParameter('database_host');,只需做$host = $container-&gt;getParameter('database_host');

    另外,从不将容器注入到服务中。直接注入@doctrine.orm.entity_manager 服务即可。

    【讨论】:

    • :D 嗯...那是真的...但参数不是重点...我删除了令人困惑的代码。
    • @MarkusKottländer 两个 never ever 陈述仍然成立。您可以将您的实际用例添加到您的问题中吗? (我无法想象您只想在构建缓存时从容器中获取值,您可能想要使用编译器传递以外的其他东西)
    • 服务可以标记为菜单项,也可以将@MenuItem 注释添加到控制器动作中以自动为该动作生成菜单项。编译器传递然后收集所有这些并将它们传递给菜单构建器服务。我需要在更大的 crm 上下文中使用它。
    • 你应该在你的菜单服务中为此使用一个事件,在编译期间你实际上还不能使用任何像学说这样的服务。 check the knpMenuBundle documentation 他们做的正是你需要做的。
    猜你喜欢
    • 1970-01-01
    • 2018-11-09
    • 2015-07-10
    • 1970-01-01
    • 1970-01-01
    • 2019-07-13
    • 1970-01-01
    • 1970-01-01
    • 2016-10-27
    相关资源
    最近更新 更多