搜索

首页  >  问答  >  正文

Symfony 6父控制器到子控制器的依赖注入

<p>我有一个基础控制器类,其中包含一些所有子控制器都会使用的实用方法。目前它有3个依赖项,但将来可能会有更多。因此,每当我想要向子控制器添加一个依赖项时,我现在遇到了一个问题,即我认为依赖注入的指令过多。</p> <pre class="brush:php;toolbar:false;">abstract class BaseController extends AbstractController { public function __construct( protected readonly SerializerInterface $serializer, protected readonly ValidatorInterface $validator, private readonly ResponseGenerator $responseGenerator, ) { } ... } class ChildController extends BaseController { // 所有父类注入在所有子类中都是必需的。 public function __construct( SerializerInterface $serializer, ValidatorInterface $validator, ResponseGenerator $responseGenerator, private readonly SomeRepository $someRepository, ... 在这里插入任何其他子控制器特定的依赖项。 ) { parent::__construct($serializer, $validator, $responseGenerator); } ... }</pre> <p>我尝试在基础控制器中使用<code>$this->container->get('serializer')</code>,但这不起作用,因为<code>AbstractController::$container</code>是通过注入定义的,但没有构造函数,所以无法调用<code>parent::__construct()</code>。此外,它也无法给我提供<code>validator</code>,所以即使它起作用,也只能解决部分问题。</p> <p>我尝试寻找可以使用的属性,例如</p> <pre class="brush:php;toolbar:false;">abstract class BaseController extends AbstractController { #[Inject] protected readonly SerializerInterface $serializer; #[Inject] protected readonly ValidatorInterface $validator;</pre> <p>但是没有找到类似的东西(PHP-DI有,但Symfony没有)。</p> <p>有没有办法以某种方式消除子控制器中的重复依赖项?</p>
P粉208469050P粉208469050499 天前560

全部回复(1)我来回复

  • P粉464208937

    P粉4642089372023-08-18 00:22:33

    你需要的是被称为服务订阅者

    在Symfony中,当控制器继承AbstractController时,它们是服务订阅者,这意味着它们被注入了一个包含一些常用服务(如twig、序列化器、表单构建器等)的小容器。

    如果你想要一些你的子控制器将使用的“常见”服务,你可以通过在父控制器中重写getSubscribedServices()来扩展列表。或者如果你的控制器没有继承Symfony提供的默认控制器,你只需要实现自己的控制器:

    如果你的控制器是一个服务(我猜已经是了),Symfony将使用setter注入将容器注入到你的控制器中。

    代码将如下所示:

    <?php
    
    use Symfony\Contracts\Service\ServiceSubscriberInterface;
    
    
    class ParentController implement ServiceSubscriberInterface {
        protected ContainerInterface $container;
        public function setContainer(ContainerInterface) { $this->container = $container; } 
    
        public static function getSubscribedServices() {
             // 这是静态的,所以Symfony可以在不实例化控制器的情况下“看到”所需的服务。
             // 在这里定义一些常见的服务,一个示例在Symfony的AbstractController中
        }
    }
    
    class ChildController extends ParentController {
        // 使用自定义DI来为子控制器提供服务。
    
        public function indexAction {
            // 你可以使用$this->container->get(...)来获取服务
        }
    
    }

    回复
    0
  • 取消回复