我没有写"我尝试了什么"或"什么不起作用",因为我可以想出很多方法来实现这样的东西。但我不敢相信以前没有人做过类似的事情,这就是为什么我想问这个问题,看看出现了什么样的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
运行代码时,日志文件中会存储时间戳,仅用于演示。