Doctrine2 - 属性更改触发事件(PropertyChangeListener) [英] Doctrine2 - Trigger event on property change (PropertyChangeListener)

查看:242
本文介绍了Doctrine2 - 属性更改触发事件(PropertyChangeListener)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我不会写我尝试什么/什么不工作,因为我可以想到许多方法来实现这样的事情。但我不能相信没有人这样做,这就是为什么我想在这里提出问题,看看什么样的Doctrine2最佳实践出现。



我想要的是触发属性更改的事件。所以假设我有一个具有 $ active 属性的实体,并且我想要一个 EntityBecameActive 事件为每个实体触发该属性从 false 更改为 true



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



所以我有一些实体这个:

 <?php 

命名空间Application\Entity;

class Entity
{
/ **
* @var int
* @ ORM\Id
* @ ORM\Column (类型= 整数);
* @ ORM\GeneratedValue(strategy =AUTO)
* /
protected $ id;

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

/ **
*获取活动。
*
* @return string
* /
public function getActive()
{
return $ this-> active;
}

/ **
*活动。
*
* @return string
* /
public function isActive()
{
return $ this-> active;
}

/ **
*设置为活动。
*
* @param bool $ active
* @return self
* /
public function setActive($ active)
{
$ this-> active = $ active;
return $ this;
}
}


解决方案

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


NOTIFY策略是基于以下假设:实体通知
感兴趣的监听者更改他们的属性。为此,要使用此策略的
a类需要从Doctrine\Common命名空间中实现
NotifyPropertyChanged接口。


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

  class MyEntity extends DomainObject 
{
私人$数据;
// ...其他字段像往常一样

public function setData($ data){
if($ data!= $ this-> data){//检查:实际上是修改了吗?
$ this-> onPropertyChanged('data',$ this-> data,$ data);
$ this-> data = $ data;
}
}
}

更新






这是一个完整的例子,但愚蠢的一个,所以你可以按照你的意愿工作。它只是演示了你如何做,所以不要太认真!



实体

 命名空间Football \TeamBundle\Entity; 

使用Doctrine\ORM\Mapping作为ORM;

/ **
* @ ORM\Entity
* @ ORM\Table(name =country)
* /
class国家扩展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;

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

/ **
*设置代码
*
* @param string $ code
* @return国家
* /
public function setCode($ code)
{
if($ code!= $ this-> code){
$ this-> onPropertyChanged('code' ,$ this-> code,$ code);
$ this-> code = $ code;
}

return $ this;
}

/ **
*获取代码
*
* @return string
* /
public function getCode )
{
return $ this-> code;
}
}

domainobject

 命名空间Football \TeamBundle\Entity; 

使用Doctrine\Common\NotifyPropertyChanged;
使用Doctrine\Common\PropertyChangedListener;

抽象类DomainObject实现NotifyPropertyChanged
{
private $ listeners = array();

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

保护函数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。\\\
。time());
}
}
}
}

strong>控制器

 命名空间Football \TeamBundle\Controller; 

使用Symfony\Bundle\FrameworkBundle\Controller\Controller;
使用Football\TeamBundle\Entity\Country;

class DefaultController extends Controller
{
public function indexAction()
{
//首先运行此命令创建或仅在DB $ b中手动平移$ b $ this-> createAction('AB');
//运行它来更新它
$ 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-> persistent($ 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



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


I not writing "what did I try/what is not working" since I can think of many ways to implement something like this. But I cannot believe that no one did this before and that is why I would like to ask the question here to see what kind of Doctrine2 best practices show up.

What I want is to trigger an event on a property change. So let's say I have an entity with an $active property and I want a EntityBecameActive event to fire for each entity when the property changes from false to true.

Other libraries often have a PropertyChanged event but there is no such thing available in Doctrine2.

So I have some entity like this:

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

解决方案

Maybe ChangeTracking Policy is what you want, maybe it is not!

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.

Check full example in link above.

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

UPDATE


This is a full example but silly one so you can work on it as you wish. It just demonstrates how you do it, so don't take it too serious!

entity

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

controller

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

And have this file with 777 permissions (again, this is test) to it: src/Football/TeamBundle/Entity/log.txt

When you run the code, your log file will have timestamp stored in it, just for demonstration purposes.

这篇关于Doctrine2 - 属性更改触发事件(PropertyChangeListener)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆