针对活动类的Symfony DI

时间:2019-05-06 13:11:49

标签: php symfony events dependency-injection

我的项目中有一些使用DI的事件。当我的事件是App \ Manager \ ValidatorAwareInterface的实例时,我将其配置为注入@validator服务。

当我在services.yaml中有此代码时,它会起作用:

services:
    _instanceof:
        App\Manager\Validator\ValidatorAwareInterface:
            calls:
                -   method: setValidator
                    arguments:
                        - '@validator'

但是当我将相同的代码放入导入到services.yaml中的manager.yaml文件中时,它不再起作用:

imports:
    - { resource: manager.yaml }

您知道为什么吗?

谢谢。

2 个答案:

答案 0 :(得分:1)

我认为您应该在定义其他服务之前将symfony的默认服务配置复制到manager.yaml中,因为默认配置仅应用于该文件中定义的服务。 The new Default services.yaml File

# config/manager.yaml
services:
    # default configuration for services in *this* file
    _defaults:
        autowire: true      # Automatically injects dependencies in your services.
        autoconfigure: true # Automatically registers your services as commands, event subscribers, etc.
        public: false       # Allows optimizing the container by removing unused services; this also means
                            # fetching services directly from the container via $container->get() won't work.
                            # The best practice is to be explicit about your dependencies anyway.

    # makes classes in src/ available to be used as services
    # this creates a service per class whose id is the fully-qualified class name
    App\:
        resource: '../src/*'
        exclude: '../src/{Entity,Migrations,Tests}'

    # controllers are imported separately to make sure services can be injected
    # as action arguments even if you don't extend any base controller class
    App\Controller\:
        resource: '../src/Controller'
        tags: ['controller.service_arguments']

    # add more service definitions when explicit configuration is needed
    # please note that last definitions always *replace* previous ones

答案 1 :(得分:1)

@ stephan.mada的答案可能会解决您的问题。

但是我想指出一个鲜为人知的注释,称为“ @required”,它根本不需要显式配置设置程序。

use Symfony\Component\Validator\Validator\ValidatorInterface;

trait ValidatorTrait
{
    /** @var ValidatorInterface */
    protected $validator;

    /** @required */
    public function injectValidator(ValidatorInterface $validator)
    {
        $this->validator = $this->validator ?: $validator;
    }
}

注入方法之前的'@required'使容器自动注入依赖项。您在services.yaml中的二传手可以完全消失。您不会看到很多'@required'用法,但对于通常注入的服务确实很方便。

您可能还会注意到我在这里使用了一个特征。具有特征,我不再需要基类或接口。任何使用特征的服务都将自动注入验证程序服务。当然,您可以根据需要使用常规类。

class SomeService
{
    use ValidatorTrait; // And the validator is now available
    use RouterTrait;    // As well as the router

最后一点。我添加了一个保护措施以确保验证器只能注入一次。这样可以防止流氓程序员在循环中的其他时间点倾向于注入其他验证器。