【问题标题】:Symfony 2 one entity event listener is running on every entity loadSymfony 2 一个实体事件监听器在每个实体负载上运行
【发布时间】:2015-06-01 16:11:02
【问题描述】:

我是 Symfony 的新手,关注 the Jobeet tutorial。我有三个实体 - 工作、类别和用户。我有以下服务监听器。

src/Ibw/JobeetBundle/Resources/config/services.yml

services:
    ibw.jobeet.entity.job.container_aware:
        class: Ibw\JobeetBundle\Doctrine\Event\Listener\JobListener
        calls:
            - [setContainer, ["@service_container"]]
        tags:
            - { name: doctrine.event_listener, event: postLoad }

src/Ibw/JobeetBundle/Doctrine/Event/Listener/JobListener.php

<?php
namespace Ibw\JobeetBundle\Doctrine\Event\Listener;

use Symfony\Component\DependencyInjection\ContainerInterface;
use Doctrine\ORM\Event\LifecycleEventArgs;

class JobListener
{
    /** @var ContainerInterface */
    protected $container;

    /**
    * @param ContainerInterface @container
    */
    public function setContainer(ContainerInterface $container)
    {
        $this->container = $container;
    }

    /**
     * @ORM\PostLoad
     */
    public function postLoad(LifecycleEventArgs $eventArgs)
    {
        $entity = $eventArgs->getEntity();
        if (method_exists($entity, 'setContainer')) {
            $entity->setContainer($this->container);
        }
    }
}

我预计 postLoad 只会为 Job 实体调用,但我发现它也为其他两个实体 CategoryUser 调用。我只在 Job 实体中定义setContainer。所以,我得到了其他实体的未定义方法。我的解决方法是与method_exists 联系。

有没有办法只在特定实体上运行postLoad

【问题讨论】:

标签: php symfony symfony-2.6


【解决方案1】:

更新答案

您的示例是一个事件侦听器,但根据您的描述,您需要一个entity listener,因此请查看下面的示例。

  • 实体侦听器可以是任何类,默认情况下它应该是具有无参数构造函数的类。
  • 与实现事件侦听器不同,实体侦听器仅针对指定实体调用。
  • 实体侦听器方法接收两个参数,实体实例和生命周期事件。

实体

namespace Your\WhateverBundle\Entity;

use Doctrine\ORM\Mapping as ORM;

/**
 * @ORM\Entity
 * @ORM\EntityListeners({"Your\WhateverBundle\EntityListener\JobListener"})
 * @ORM\Table(name="job")
 */
class Job
{
   // Your properties, getters and setters
}

实体监听器

namespace Your\WhateverBundle\EntityListener;

use Your\WhateverBundle\Entity\Job;
use Doctrine\ORM\Event\LifecycleEventArgs;
use Doctrine\ORM\Mapping as ORM;

class JobListener
{
    /** @ORM\PostLoad */
    public function postLoadHandler(Job $job, LifecycleEventArgs $args)
    {
        // Do whatever you want
    }
}

【讨论】:

  • 我认为$entity instanceof Jobmethod_exists($entity, 'setContainer') 没有什么不同。 postLoad 是为不相关的实体运行的。
  • @Sithu - 添加了更多示例,我一直在使用该逻辑没有问题。
  • 我认为doctrine.event_listener 在每次页面加载时都会运行,而不是特定实体。根据您的编辑,如果 entity.listener.user_persist: 仅附加到用户实体。我们不需要检查$entity instanceof User。我正在寻找这样的实体侦听器而不是@tetranz 回答的事件侦听器,但我还没有实现。
【解决方案2】:

如果您正在运行 Doctrine 2.4 或更高版本,则可以使用 Entity listener 而不是事件侦听器。这仅由与其关联的一个或多个实体触发。尽管我现在无法访问我的代码,但我已经在 Symfony 中成功使用了它。这是一个example,尽管它忽略了如何将侦听器与相关实体关联的重要部分。我认为它只需要根据 Doctrine 文档将 @EntityListeners({"listener service name"}) 添加到 @Entity 注释块(或者如果您不使用注释,则为 XML 或 YAML)。稍后我会检查我的代码并更正是否需要更多内容。

【讨论】:

  • 这可能是一个正确的答案,但我无法让它发挥作用。我使用 YAML 和 postLoad,但从未调用过 postLoad
【解决方案3】:

显然 Listener 类必须放在 Entity 类旁边。 有了这样的目录结构和以下配置,它看起来就像一个魅力。

# src/vendor/yourBundle/Entity/JobListener.php
namespace VENDOR\YourBundle\Entity;

use Doctrine\Common\Persistence\Event\LifecycleEventArgs;
use VENDOR\YourBundle\Entity\Job;

/**
 * Class JobListener
 * @package VENDOR\YourBundle\Entity
 */
class JobListener {

    public function postLoad( Job $job, LifecycleEventArgs $args ) {
        .....
    }
}
# src/vendor/yourBundle/Resources/config/doctrine/Job.orm.yml
VENDOR\YourBundle\Entity\Job:
type: entity
...
entityListeners:
    VENDOR\YourBundle\Entity\JobListener: ~
...

或者如果你喜欢注释

# src/vendor/yourBundle/Entity/Job.php
/**
* @ORM\Entity
* @ORM\EntityListeners({"VENDOR\YourBundle\Entity\JobListener"})
*/
class Job {
    .....
}

如果你必须在你的 Listener 中注入一些服务,你必须添加一些类似的配置。

# app/config/services.yml
# or
# src/vendor/yourBundle/Resources/config/services.yml
doctrine.job_listener:
    class: Vendor\YourBundle\Entity\JobListener
    arguments: ["Path\To\Your\Service"]
    tags:
        - { name: doctrine.orm.entity_listener }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-07-09
    • 1970-01-01
    • 1970-01-01
    • 2020-07-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-06-25
    相关资源
    最近更新 更多