gpt4 book ai didi

php - Doctrine onFlush 事件监听器服务的 Symfony 循环引用异常

转载 作者:可可西里 更新时间:2023-11-01 13:24:17 24 4
gpt4 key购买 nike

我已经为 Doctrine onFlush 事件监听器创建了一个服务。在这个监听器中,我想引用我在另一个 服务中的一个常用函数来检查实体的快捷路径。 other 服务使用实体管理器来执行此操作,因此该other 服务的服务定义将原则实体管理器作为构造函数参数注入(inject)。但是,如果我在我的主要 onFlush 事件监听器中包含该other 服务,我会收到有关循环引用的严重错误。

我可以让这个 entity_helper 服务接受集合函数 setEntityManager($entityManager) 中的实体管理器。但这意味着每当我在其他任何地方使用此 entity_helper 服务时,我都必须始终传入 EntityManager。也许这没关系,但这是这里唯一的解决方案吗?一开始我的逻辑/理解有问题吗? (我是 Symfony 的新手,所以我经常犯错)。

证据 A:严重错误

Fatal error: Uncaught exception 'Symfony\Component\DependencyInjection\Exception\ServiceCircularReferenceException' with message 'Circular reference detected for service "doctrine.dbal.cms_connection", path: "doctrine.dbal.cms_connection".' in /var/www/core/cms/vendor/symfony/symfony/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php:456 Stack trace: #0 /var/www/core/cms/vendor/symfony/symfony/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php(604): Symfony\Component\DependencyInjection\Dumper\PhpDumper->addServiceInlinedDefinitionsSetup('doctrine.dbal.c...', Object(Symfony\Component\DependencyInjection\Definition)) #1 /var/www/core/cms/vendor/symfony/symfony/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php(630): Symfony\Component\DependencyInjection\Dumper\PhpDumper->addService('doctrine.dbal.c...', Object(Symfony\Component\DependencyInjection\Definition)) #2 /var/www/core/cms/vendor/symfony/symfony/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php(117): Symfony\Componen in /var/www/core/cms/vendor/symfony/symfony/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php on line 456

服务.yml

# This is the helper class for all entities
gutensite_cms.entity_helper:
class: Gutensite\CmsBundle\Service\EntityHelper
# This causes the Circular Reference Error when this service is included in Event Listener
arguments: [ "@doctrine.orm.cms_entity_manager" ]
# Passing via a setter injection also causes the same error.
#calls:
# - [setEntityManager, ['@doctrine.orm.cms_entity_manager']]


# An event listener for any entity that is Versionable
gutensite_cms.listener.is_versionable:
class: Gutensite\CmsBundle\EventListener\IsVersionableListener
#only pass in the services we need
arguments: [ "@gutensite_cms.entity_helper" ]
tags:
- { name: doctrine.event_listener, event: onFlush }

Gutensite\CmsBundle\Service\EntityHelper

namespace Gutensite\CmsBundle\Service;

use Doctrine\ORM\EntityManager;

class EntityHelper {

/**
* @var $em EntityManager
*/
private $em;

public function __construct(EntityManager $entityManager) {
$this->em = $entityManager;
}

/**
* Get the bundle shortcut path for an entity based on it's namespace.
*
* As an example, if your entity is Gutensite\CmsBundle\Entity\View\ViewVersion the function will return
* GutensiteCmsBundle:View\ViewVersion
*
* @param $entity
* @return string
*/
public function getEntityBundleShortcut($entity) {
// wrap get_class() in the entityManager metadata function to avoid returning cached proxy class
$path = explode('\Entity\\', $this->em->getClassMetadata(get_class($entity))->getName());
return str_replace('\\', '', $path[0]).':'.$path[1];
}

}

Gutensite\CmsBundle\EventListener\IsVersionableListener

namespace Gutensite\CmsBundle\EventListener;

use Doctrine\ORM\Event\OnFlushEventArgs;
use Gutensite\CmsBundle\Service\EntityHelper;


/**
* Class IsVersionableListener
* @package Gutensite\CmsBundle\EventListener
*/
class IsVersionableListener
{

/*
private $entityHelper;

public function __construct(EntityHelper $entityHelper) {
$this->entityHelper = $entityHelper;
}
*/

public function onFlush(OnFlushEventArgs $eventArgs)
{

// This never is excecuted because of the error
print('ON FLUSH EVENT EXECUTED');
exit;

$em = $eventArgs->getEntityManager();
$uow = $em->getUnitOfWork();
$updatedEntities = $uow->getScheduledEntityUpdates();

foreach($updatedEntities AS $entity) {

// This is generic listener for all entities that have an isVersionable method (e.g. ViewVersion)
// TODO: at the moment, we only want to do the following code for the viewVersion entity

if (method_exists($entity, 'isVersionable') && $entity->isVersionable()) {

// Get the Correct Repo for this entity
$entityShortcut = $this->entityHelper->getEntityBundleShortcut($entity);
$repo = $em->getRepository($entityShortcut);

// If the repo for this entity has an onFlush method, use it.
// This allows us to keep the functionality in the entity repo
if(method_exists($repo, 'onFlush')) {
$repo->onFlush($em, $entity);
}

}
}
}
}

最佳答案

对此的基本解决方案(如我所指出的)是从服务定义(和服务类)中删除 EntityManager 的构造或 setter 注入(inject)。相反,您必须将 EntityManager 传递到需要它的函数中。这可以防止循环引用。

我选择了这个而不是创建一个 setEntityManager 因为在调用函数之前必须在 EntityHelper 服务上设置它似乎很笨拙。直接将它传递给需要它的函数似乎更好。

更改如下:

服务.yml

# This is the helper class for all entities
gutensite_cms.entity_helper:
class: Gutensite\CmsBundle\Service\EntityHelper
# Do NOT pass in EntityManager via constructor or injector, because it causes a Circular Reference Error when this service is included in Event Listener


# An event listener for any entity that is Versionable
gutensite_cms.listener.is_versionable:
class: Gutensite\CmsBundle\EventListener\IsVersionableListener
#only pass in the services we need
arguments: [ "@gutensite_cms.entity_helper" ]
tags:
- { name: doctrine.event_listener, event: onFlush }

Gutensite\CmsBundle\Service\EntityHelper

namespace Gutensite\CmsBundle\Service;

use Doctrine\ORM\EntityManager;

class EntityHelper {


/**
* Get the bundle shortcut path for an entity based on it's namespace.
*
* As an example, if your entity is Gutensite\CmsBundle\Entity\View\ViewVersion the function will return
* GutensiteCmsBundle:View\ViewVersion
*
* @param $entity
* @return string
*/
public function getEntityBundleShortcut(EventManager $eventManager, $entity) {
// wrap get_class() in the entityManager metadata function to avoid returning cached proxy class
$path = explode('\Entity\\', $eventManager->getClassMetadata(get_class($entity))->getName());
return str_replace('\\', '', $path[0]).':'.$path[1];
}

}

Gutensite\CmsBundle\EventListener\IsVersionableListener

namespace Gutensite\CmsBundle\EventListener;

use Doctrine\ORM\Event\OnFlushEventArgs;
use Gutensite\CmsBundle\Service\EntityHelper;


/**
* Class IsVersionableListener
* @package Gutensite\CmsBundle\EventListener
*/
class IsVersionableListener
{

/*
private $entityHelper;

public function __construct(EntityHelper $entityHelper) {
$this->entityHelper = $entityHelper;
}
*/

public function onFlush(OnFlushEventArgs $eventArgs)
{

$em = $eventArgs->getEntityManager();
$uow = $em->getUnitOfWork();
$updatedEntities = $uow->getScheduledEntityUpdates();

foreach($updatedEntities AS $entity) {

// This is generic listener for all entities that have an isVersionable method (e.g. ViewVersion)
// TODO: at the moment, we only want to do the following code for the viewVersion entity

if (method_exists($entity, 'isVersionable') && $entity->isVersionable()) {

// Get the Correct Repo for this entity
$entityShortcut = $this->entityHelper->getEntityBundleShortcut($em, $entity);
$repo = $em->getRepository($entityShortcut);

// If the repo for this entity has an onFlush method, use it.
// This allows us to keep the functionality in the entity repo
if(method_exists($repo, 'onFlush')) {
$repo->onFlush($em, $entity);
}

}
}
}
}

关于php - Doctrine onFlush 事件监听器服务的 Symfony 循环引用异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25577801/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com