Doctrine2-属性更改的触发器事件(PropertyChangeListener)


Doctrine2 - Trigger event on property change (PropertyChangeListener)

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


我想要的是在属性更改时触发一个事件。假设我有一个具有$active属性的实体,并且当属性从false更改为true时,我希望为每个实体激发一个EntityBecameActive事件。

其他库通常有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 Policy是您想要的,也许不是!

NOTIFY策略基于实体通知感兴趣的侦听器对其属性的更改。为此目的,想要使用此策略的类需要实现NotifyPropertyChanged接口来自Doctrine''Common命名空间。

查看上面链接中的完整示例。

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

运行代码时,日志文件中会存储时间戳,仅用于演示。