2015-07-02 143 views
1

我不寫「我嘗試了什麼」或「什麼不工作」,因爲我可以想出很多方法來實現這樣的事情。但我不相信之前沒有人做過類似的事情,這就是爲什麼我想問這個問題,看看什麼樣的Doctrine2最佳實踐出現。Doctrine2 - 屬性更改觸發事件(PropertyChangeListener)


我想要的是觸發屬性更改事件。假設我有一個具有$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; 
    } 
} 

回答

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

UPDATE


這是一個完整的例子,但癡心一片,所以你可以根據需要進行這項工作。它只是演示你如何做,所以不要太認真!

實體

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

而且有這個文件機智h 777權限(再次,這是測試):src/Football/TeamBundle/Entity/log.txt

當您運行代碼時,您的日誌文件將存儲時間戳,僅用於演示目的。

+0

這看起來確實很有趣,我會潛水在文檔:) – Wilt

+0

我用它與你的原因相同,所以看看它是否滿足你的確切需求。 – BentCoder

+0

另請參見http://doctrine-orm.readthedocs.org/en/latest/reference/change-tracking-policies.html – BentCoder

相關問題