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
当您 运行 代码时,您的日志文件将存储时间戳,仅用于演示目的。
我不写 "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
当您 运行 代码时,您的日志文件将存储时间戳,仅用于演示目的。