Doctrine2 - 属性 变化触发事件(PropertyChangeListener)

Doctrine2 - Trigger event on property change (PropertyChangeListener)

我不写 "what did I try" 或 "what is not working" 因为我可以想出很多方法来实现这样的东西。但我不敢相信以前没有人做过类似的事情,这就是为什么我想问这个问题,看看出现了什么样的 Doctrine2 最佳实践。


我想要的是在 属性 更改时触发事件。因此,假设我有一个带有 $active 属性 的实体,并且我希望在 属性 从 false 变为 [ 时为每个实体触发 EntityBecameActive 事件=15=].

其他库通常有一个 PropertyChanged 事件,但在 Doctrine2 中没有这样的东西。

所以我有这样的实体:

<?php

namespace Application\Entity;

class Entity
{
    /**
     * @var int
     * @ORM\Id
     * @ORM\Column(type="integer");
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    protected $id;

    /**
     * @var boolean
     * @ORM\Column(type="boolean", nullable=false)
     */
    protected $active = false;

    /**
     * Get active.
     *
     * @return string
     */
    public function getActive()
    {
        return $this->active;
    }

    /**
     * Is active.
     *
     * @return string
     */
    public function isActive()
    {
        return $this->active;
    }

    /**
     * Set active.
     *
     * @param bool $active
     * @return self
     */
    public function setActive($active)
    {
        $this->active = $active;
        return $this;
    }
}

也许ChangeTracking政策是你想要的,也许不是!

The NOTIFY policy is based on the assumption that the entities notify interested listeners of changes to their properties. For that purpose, a class that wants to use this policy needs to implement the NotifyPropertyChanged interface from the Doctrine\Common namespace.

查看上面 link 中的完整示例。

class MyEntity extends DomainObject
{
    private $data;
    // ... other fields as usual

    public function setData($data) {
        if ($data != $this->data) { // check: is it actually modified?
            $this->onPropertyChanged('data', $this->data, $data);
            $this->data = $data;
        }
    }
}

更新


这是一个完整的示例,但很愚蠢,因此您可以按照自己的意愿进行处理。它只是演示你如何做,所以不要太认真!

实体

namespace Football\TeamBundle\Entity;

use Doctrine\ORM\Mapping as ORM;

/**
 * @ORM\Entity
 * @ORM\Table(name="country")
 */
class Country extends DomainObject
{
    /**
     * @var int
     *
     * @ORM\Id
     * @ORM\Column(type="smallint")
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    protected $id;

    /**
     * @var string
     *
     * @ORM\Column(type="string", length=2, unique=true)
     */
    protected $code;

    /**
     * Get id
     *
     * @return integer
     */
    public function getId()
    {
        return $this->id;
    }

    /**
     * Set code
     *
     * @param string $code
     * @return Country
     */
    public function setCode($code)
    {
        if ($code != $this->code) {
            $this->onPropertyChanged('code', $this->code, $code);
            $this->code = $code;
        }

        return $this;
    }

    /**
     * Get code
     *
     * @return string
     */
    public function getCode()
    {
        return $this->code;
    }
}

域对象

namespace Football\TeamBundle\Entity;

use Doctrine\Common\NotifyPropertyChanged;
use Doctrine\Common\PropertyChangedListener;

abstract class DomainObject implements NotifyPropertyChanged
{
    private $listeners = array();

    public function addPropertyChangedListener(PropertyChangedListener $listener)
    {
        $this->listeners[] = $listener;
    }

    protected function onPropertyChanged($propName, $oldValue, $newValue)
    {
        $filename = '../src/Football/TeamBundle/Entity/log.txt';
        $content = file_get_contents($filename);

        if ($this->listeners) {
            foreach ($this->listeners as $listener) {
                $listener->propertyChanged($this, $propName, $oldValue, $newValue);

                file_put_contents($filename, $content . "\n" . time());
            }
        }
    }
}

控制器

namespace Football\TeamBundle\Controller;

use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Football\TeamBundle\Entity\Country;

class DefaultController extends Controller
{
    public function indexAction()
    {
        // First run this to create or just manually punt in DB
        $this->createAction('AB');
        // Run this to update it
        $this->updateAction('AB');

        return $this->render('FootballTeamBundle:Default:index.html.twig', array('name' => 'inanzzz'));
    }

    public function createAction($code)
    {
        $em = $this->getDoctrine()->getManager();
        $country = new Country();
        $country->setCode($code);
        $em->persist($country);
        $em->flush();
    }

    public function updateAction($code)
    {
        $repo = $this->getDoctrine()->getRepository('FootballTeamBundle:Country');
        $country = $repo->findOneBy(array('code' => $code));
        $country->setCode('BB');

        $em = $this->getDoctrine()->getManager();
        $em->flush();
    }
}

并让这个文件拥有 777 权限(同样,这是测试):src/Football/TeamBundle/Entity/log.txt

当您 运行 代码时,您的日志文件将存储时间戳,仅用于演示目的。