依赖注入通过 __construct() 到 Symfony/Doctrine EntityListener

问题描述 投票:0回答:2

我正在努力解决以下问题:

我为我的一个实体创建了一个 EntityListener。

namespace App\Event\EventListener\Vendor;

use App\Entity\Vendor;
use Doctrine\ORM\Event\PreUpdateEventArgs;
use Symfony\Component\Messenger\MessageBusInterface;

class VendorListener
{
    private MessageBusInterface $messageBus;

    public function __construct(MessageBusInterface $messageBus)
    {
        $this->messageBus = $messageBus;
    }


    public function preUpdate(
        Vendor $vendor,
        PreUpdateEventArgs $args,
    ) {

        if ($args->hasChangedField('blacklistStatus')) {
            if ($args->getNewValue('blacklistStatus')) {
                //do something


            } 
        }
    }
}

在尊重实体中,我通过注释“附加”了它。

<?php

namespace App\Entity;

use App\Event\EventListener\Vendor\VendorListener;
use Doctrine\ORM\Mapping as ORM;

#[ORM\Entity(repositoryClass: VendorRepository::class)]
#[ORM\EntityListeners([VendorListener::class])]
class Vendor
{

...
}

我的 service.yaml 文件如下所示,如官方 docs 中所述。

App\Event\EventListener\Vendor\VendorListener:
    tags:
        -
          name: doctrine.orm.entity_listener
          entity: App\Entity\Vendor
          event: preUpdate

监听器工作并按预期触发,但只要我注释掉构造方法。 如果我尝试通过构造函数访问 EntityListener 中的某些服务,我会显示以下错误消息:

函数 App\Event\EventListener\Vendor\VendorListener::__construct() 的参数太少,在第 82 行 C:\Users\Admin\Desktop odensee endor\doctrine\doctrine-bundle\Mapping\ContainerEntityListenerResolver.php 中传递了 0正好是 1 个预期

我错过了什么吗?或者现在是否可以将服务自动连接到学说实体监听器中,因为出于某种原因它们不是由 symfony 启动的,而是由学说启动的?

我发现了一个有趣的 thread 谈论我遇到的问题。遗憾的是,建议的解决方案不起作用。

symfony dependency-injection doctrine autowired event-listener
2个回答
1
投票
#[ORM\EntityListeners([VendorListener::class])]

这是 doctrine 监听器,不是 symfony 监听器。 Autowire 仅适用于 symfony 监听器。

您可以创建一个实现

Doctrine\Common\EventSubscriber
的侦听器。没有
service.yaml
配置和实体注释
ORM\EntityListeners
.
只有一节课
VendorListener

namespace App\EventListener\Doctrine;

use Doctrine\Common\EventSubscriber;
use Doctrine\ORM\Event\PreUpdateEventArgs;
use Doctrine\ORM\Events;
use Symfony\Component\Messenger\MessageBusInterface;

class VendorListener implements EventSubscriber
{
    private MessageBusInterface $messageBus;

    public function __construct(MessageBusInterface $messageBus)
    {
        $this->messageBus = $messageBus;
    }


    public function preUpdate(PreUpdateEventArgs $args)
    {
        if (!$args->getObject() instanceof Vendor) {
            return;
        }

        if ($args->hasChangedField('blacklistStatus')) {
            if ($args->getNewValue('blacklistStatus')) {
                //do something
            }
        }
    }

    public function getSubscribedEvents(): array
    {
        return [
            Events::preUpdate => 'preUpdate',
        ];
    }
}

0
投票

以下解决方案现在对我有效:

而不是通过注释将 EntityListener 附加到相应的实体,例如

#[ORM\Entity(repositoryClass: VendorRepository::class)]
#[ORM\EntityListeners([VendorListener::class])]
class Vendor
{

...
}

在 EntityListener 本身中配置目标实体,如此处所述

use App\Entity\Vendor;
use Doctrine\Bundle\DoctrineBundle\Attribute\AsEntityListener;
use Doctrine\ORM\Event\PreUpdateEventArgs;
use Doctrine\ORM\Events;
use Symfony\Component\Messenger\MessageBusInterface;

#[AsEntityListener(event: Events::preUpdate, method: 'preUpdate', entity: Vendor::class)]
class VendorListener
{
...
}

有了这个,通过构造函数的依赖注入是可能的。原因似乎是

ORM\EntityListeners()
由学说本身处理,这使它们无法访问容器。

© www.soinside.com 2019 - 2024. All rights reserved.