Php 将SecurityContext注入Symfony2中的侦听器Preperist或preUpdate以获取createdBy或updatedBy中的用户会导致循环引用错误

Php 将SecurityContext注入Symfony2中的侦听器Preperist或preUpdate以获取createdBy或updatedBy中的用户会导致循环引用错误,php,doctrine-orm,symfony,Php,Doctrine Orm,Symfony,我设置了一个listener类,在其中我将在任何doctrine prePersist上设置ownerid列。我的services.yml文件如下所示 services: my.listener: class: App\SharedBundle\Listener\EntityListener arguments: ["@security.context"] tags: - { name: doctrine.event_listener, event: pr

我设置了一个listener类,在其中我将在任何doctrine prePersist上设置ownerid列。我的services.yml文件如下所示

services:
my.listener:
    class: App\SharedBundle\Listener\EntityListener
    arguments: ["@security.context"]
    tags:
        - { name: doctrine.event_listener, event: prePersist }
我的班级看起来像这样

use Doctrine\ORM\Event\LifecycleEventArgs;
use Symfony\Component\Security\Core\SecurityContextInterface;

class EntityListener
{

protected $securityContext;

public function __construct(SecurityContextInterface $securityContext)
{
    $this->securityContext = $securityContext;
}


/**
 *
 * @param LifecycleEventArgs $args 
 */
public function prePersist(LifecycleEventArgs $args)
{

    $entity = $args->getEntity();
    $entityManager = $args->getEntityManager();

    $entity->setCreatedby();

}
}
此操作的结果是以下错误

ServiceCircularReferenceException:检测到服务“条令.orm.default\u实体\u管理器”的循环引用,路径:“条令.orm.default\u实体\u管理器->条令.dbal.default\u连接->my.listener->security.context->security.authentication.manager->fos\u用户\u管理器”


我的假设是,安全上下文已经被注入到链中的某个地方,但我不知道如何访问它。有什么想法吗

我遇到了类似的问题,唯一的解决方法是在构造函数中传递整个容器(
参数:['@service\u container']


我使用条令配置文件设置
preUpdate
prePersist
方法:

Project\MainBundle\Entity\YourEntity:
    type: entity
    table: yourentities
    repositoryClass: Project\MainBundle\Repository\YourEntitytRepository
    fields:
        id:
            type: integer
            id: true
            generator:
                strategy: AUTO

    lifecycleCallbacks:
        prePersist: [methodNameHere]
        preUpdate: [anotherMethodHere]

方法是在实体中声明的,这样你就不需要侦听器,如果你需要一个更通用的方法,你可以创建一个BaseEntity来保留这个方法并扩展其他实体。希望有帮助

自Symfony 2.6起,此问题应得到修复。一个拉入请求刚刚被接受到主机中。这里描述了您的问题。


从Symfony 2.6开始,您可以将
security.token\u存储
注入侦听器。此服务将包含中的
SecurityContext
使用的令牌。此线程中已经有一个很好的答案,但一切都会发生变化。现在,条令中有实体侦听器类:

因此,您可以向实体添加注释,如:

/**
 * @ORM\EntityListeners({"App\Entity\Listener\PhotoListener"})
 * @ORM\Entity(repositoryClass="App\Repository\PhotoRepository")
 */
class Photo 
{
    // Entity code here...
}
并创建一个如下所示的类:

class PhotoListener
{        
    private $container;

    function __construct(ContainerInterface $container)
    {
        $this->container = $container;
    }

    /** @ORM\PreRemove() */
    public function preRemoveHandler(Photo $photo, LifecycleEventArgs $event): void
    {
         // Some code here...
    }
}
您还应该在
services.yml
中定义此侦听器,如下所示:

photo_listener:
  class: App\Entity\Listener\PhotoListener
  public: false
  autowire: true
  tags:
    - {name: doctrine.orm.entity_listener}

奇怪的是,即使在构造函数中使用
$container->get('security.context')
设置属性也会抛出循环引用错误。但是,在成员方法中调用它很好……我觉得它就像一个
chmod 777 dir/name
,解决方案。正如中所述,它使整个概念失效。请看@LoganBibby,这应该是显而易见的,您试图实例化一个需要另一个对象的类,而该实例正是该对象所需要的,您最终将陷入一个无限循环中,而这个循环永远不会停止。当传递
容器时
你是在懒洋洋地加载你的服务,这意味着从你想要你的服务的那一刻起,它就已经被实例化了。这有点像“我需要钱买一辆车,但我需要一辆车来赚钱。”从Symfony 2.6开始,有一个更好的解决方案。请检查我的答案。肮脏的解决方案。。。这就像买整个超市只是为了做一个蛋糕。在这种情况下使用security.context如何?很好,我很高兴不再需要注入整个容器。一个不是安全令牌的服务如何?你说的Lighthart是什么意思?symfony中的安全令牌不是一项服务,有一项服务可以让您访问它:security.token\u storage。@Lighthart我在这里问了这个问题,因为它也是在我的开发过程中提出来的。如何将依赖于实体管理器的任何服务注入侦听器中。如果您有任何想法,请查看我的问题:在2.3上,您仍然可以注入服务\u容器服务。但是,我强烈建议您在升级方面付出一些努力。
/**
 * @ORM\EntityListeners({"App\Entity\Listener\PhotoListener"})
 * @ORM\Entity(repositoryClass="App\Repository\PhotoRepository")
 */
class Photo 
{
    // Entity code here...
}
class PhotoListener
{        
    private $container;

    function __construct(ContainerInterface $container)
    {
        $this->container = $container;
    }

    /** @ORM\PreRemove() */
    public function preRemoveHandler(Photo $photo, LifecycleEventArgs $event): void
    {
         // Some code here...
    }
}
photo_listener:
  class: App\Entity\Listener\PhotoListener
  public: false
  autowire: true
  tags:
    - {name: doctrine.orm.entity_listener}