【问题标题】:Symfony DI for Event classes事件类的 Symfony DI
【发布时间】:2019-05-06 13:11:49
【问题描述】:

我的项目中有一些使用 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 }

你知道为什么吗?

谢谢。

【问题讨论】:

  • 调用这个服务会出现什么错误?

标签: php symfony events dependency-injection


【解决方案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;
    }
}

inject 方法之前的“@required”会导致容器自动注入依赖项。 services.yaml 中的设置器可以完全消失。 '@required' 的用法并不多见,但它确实对通常注入的服务派上了用场。

您可能还注意到我在这里使用了一个特征。有了 trait,我不再需要基类或接口。任何使用 trait 的服务都会自动注入验证器服务。如果你愿意,当然可以只使用传统的类。

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

最后一点。我添加了一个守卫来确保验证器只能被注入一次。这可以防止流氓程序员可能会在周期的其他时间点注入不同的验证器。

【讨论】:

  • 它与 Symfony 2.8 兼容吗?我想在旧项目上使用它
  • 我不知道它是否适用于 2.8。我怀疑不是,但试试吧,让我们知道。
【解决方案2】:

我认为您应该在定义其他服务之前将 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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-02-07
    • 1970-01-01
    • 2011-07-14
    • 2018-04-26
    • 1970-01-01
    • 2012-09-25
    • 1970-01-01
    • 2012-04-23
    相关资源
    最近更新 更多