4

我是 Symfony 的新手并遵循Jobeet 教程。我有三个实体 - 工作、类别和用户。我有以下服务监听器。

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调用。我只setContainerJob实体中定义。所以,我得到了其他实体的未定义方法。我的解决方法是检查method_exists.

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

4

3 回答 3

3

更新的答案

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

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

实体

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
    }
}
于 2015-06-01T19:54:16.260 回答
2

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

于 2015-06-01T17:13:39.937 回答
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 {
    .....
}

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

# 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 }
于 2016-01-02T21:13:02.920 回答