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

时间:2015-07-02 08:27:06

标签: php events doctrine-orm eventtrigger propertychangelistener

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

我想要的是触发房产变更事件。因此,我们假设我有一个$active属性的实体,当属性从EntityBecameActive更改为false时,我希望为每个实体触发true个事件

其他库通常有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;
    }
}

1 个答案:

答案 0 :(得分:3)

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

  

NOTIFY政策基于实体通知的假设   感兴趣的听众改变他们的财产。为了这个目的,   想要使用此策略的类需要实现   来自Doctrine \ Common命名空间的NotifyPropertyChanged接口。

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

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

<强> domainObject的

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

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