Symfony 2一个实体事件侦听器正在每个实体加载上运行

时间:2015-06-01 16:11:03

标签: php symfony symfony-2.6

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

的src / IBW / JobeetBundle /资源/配置/ 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 /学说/事件/侦听/ 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,但我发现其他两个实体类别用户即可。我只在作业实体中定义setContainer。所以,我得到了其他实体的未定义方法。我的解决方法是与method_exists核对。

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

3 个答案:

答案 0 :(得分:3)

更新的答案

您的示例是一个事件监听器,但根据您的说明,您需要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
}

<强> EntityListener

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
    }
}

答案 1 :(得分:2)

如果您正在运行Doctrine 2.4或更高版本,则可以使用Entity listener而不是事件侦听器。这仅由与其关联的实体或实体触发。我已经在Symfony中成功使用了这个,尽管我现在无法访问我的代码。这是一个example,虽然它错过了将听众与相关实体联系起来的重要部分。我认为只需要根据Doctrine文档将@EntityListeners({“监听器服务名称”})添加到@Entity注释块(或XML或YAML,如果您没有使用注释)。我会稍后检查我的代码并更正是否需要更多代码。

答案 2 :(得分:1)

显然,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 }