1 回答
TA贡献1801条经验 获得超8个赞
请注意,此答案已使用新信息再次更新。
标签controller.service_arguments
只需要允许动作注入。坚持使用构造函数注入,__invoke()
这就是您所需要的。
下面的公共添加是一项要求,但事实证明您不需要编译器传递,它可以在 services.yaml 级别完成。因此,您唯一需要的是以下内容:
services: _defaults: autowire: true autoconfigure: true public: true // <---- This is the new additional config.
然后,任何类都可以用作routes.yaml
控制器并且构造注入工作得很好。
注:原答案如下。感谢 Jakumi 为我指明了正确的方向。
您需要添加一个编译器传递来做两件事。在启动和注册自动依赖注入的东西时,如果一个类的Controller
名称中有:
添加标签
controller.service_arguments
,这是您通常需要手动添加的标签services.yaml
以允许 setter 注入(如果您不关心 setter 注入,可以忽略它)将类设置为公共的,因为 Symfony 有一个奇怪的想法,即公共或私有的概念不能从类访问修饰符中推断出来(真的吗?)——这是重要的事情,因为 Symfony 会抱怨控制器是私有的,否则
不要忘记您不必使用“名称控制器”的逻辑。它可以是“Controller”在类名的末尾,这可能更好。
不管怎样,先创建一个CompilerPass
. 把它放在任何你想要的地方。我把我的放在旁边Kernel.php
。
use Symfony\Component\DependencyInjection\{Compiler\CompilerPassInterface, ContainerBuilder};
class ControllersAsServices implements CompilerPassInterface
{
public function process(ContainerBuilder $container)
{
foreach ($container->getDefinitions() as $definition) {
if (strpos($definition->getClass(), "Controller") === false) {
continue;
}
$definition->addTag("controller.service_arguments");
$definition->setPublic(true);
}
}
}
然后在你的Kernel.php,你需要告诉它使用这个新的。覆盖受保护的函数build并添加您的编译器传递,如文档所示:
protected function build(ContainerBuilder $container)
{
$container->addCompilerPass(new ControllersAsServices, PassConfig::TYPE_BEFORE_OPTIMIZATION, -1);
parent::build($container);
}
清除您的开发缓存。在我这样做之前,我没有任何改变。
现在,任何Controller名称中带有的类都可以像最初那样被自动装配。
下面是来自 Jakumi 的原始答案:
我相信在你的情况下最好的方法是实现一个 CompilerPass,将类添加到容器中:
https://symfony.com/doc/current/bundles/extension.html#adding-classes-to-compile
在此过程中,可能还有一种方法可以添加标签。
Symfony 通过RegisterControllerArgumentLocatorsPass迎合 controller.service_arguments 标签,它解析构造函数参数并检查一些特征。如果你让你的编译器传递优先级更高,那么你可能很容易解决这个问题......
- 1 回答
- 0 关注
- 94 浏览
添加回答
举报