2011-10-31 61 views
4

我在Zend Framework應用程序中使用Doctrine 2,需要類似於Zend_Validate_Db_RecordExists和Zend_Validate_Db_NoRecordExists的功能。Zend_Validate_Db_RecordExists與Doctrine 2?

例如,當用戶輸入一個新項目時,我需要驗證重複條目不存在。通過在表單上添加Db_NoRecordExists驗證器,Zend_Db很容易完成。

我試着實現了自定義驗證器解決方案here,但我無法弄清楚它們如何與Doctrine進行通信來檢索實體(我懷疑這種方法可能不再適用於Post-Doctrine 1.x)。

Doctrine手冊的FAQ部分建議從客戶端代碼中調用contains(),但這隻包含集合,並且如果可能的話,我想要在我的表單模型中始終處理所有的表單驗證。

任何人都可以提出一種方法來使用這些Zend驗證與Doctrine 2 DBAL配置爲數據庫連接/資源?

+0

到目前爲止,感謝兩位響應者。研究你的代碼 - 我在ZF中使用插件/自定義類還是很新的。一旦我找到工作,將會選擇一個答案。 – cantera

回答

3

這是很簡單的,真的。

我有幾個Zend_Validate類型的驗證器與Doctrine ORM交談,所以我有一個抽象類,他們下降。

這裏的抽象類:

<?php 
namespace TimDev\Validate\Doctrine; 

abstract class AbstractValidator extends \Zend_Validate_Abstract{ 
    /** 
    * @var Doctrine\ORM\EntityManager 
    */ 
    private $_em; 


    public function __construct(\Doctrine\ORM\EntityManager $em){ 
    $this->_em = $em; 
    } 

    public function em(){ 
    return $this->_em; 
    } 
} 

這裏是我的NoEntityExists驗證:

<?php 
namespace TimDev\Validate\Doctrine; 

class NoEntityExists extends AbstractValidator{ 

    private $_ec = null; 
    private $_property = null; 
    private $_exclude = null; 

    const ERROR_ENTITY_EXISTS = 1; 

    protected $_messageTemplates = array(
    self::ERROR_ENTITY_EXISTS => 'Another record already contains %value%' 
); 

    public function __construct($opts){ 
    $this->_ec = $opts['class']; 
    $this->_property = $opts['property']; 
    $this->_exclude = $opts['exclude']; 
    parent::__construct($opts['entityManager']); 

    } 

    public function getQuery(){ 
    $qb = $this->em()->createQueryBuilder(); 
    $qb->select('o') 
      ->from($this->_ec,'o') 
      ->where('o.' . $this->_property .'=:value'); 

    if ($this->_exclude !== null){ 
     if (is_array($this->_exclude)){ 

     foreach($this->_exclude as $k=>$ex){      
      $qb->andWhere('o.' . $ex['property'] .' != :value'.$k); 
      $qb->setParameter('value'.$k,$ex['value'] ? $ex['value'] : ''); 
     } 
     } 
    } 
    $query = $qb->getQuery(); 
    return $query; 
    } 
    public function isValid($value){ 
    $valid = true; 

    $this->_setValue($value); 

    $query = $this->getQuery(); 
    $query->setParameter("value", $value); 

    $result = $query->execute(); 

    if (count($result)){ 
     $valid = false; 
     $this->_error(self::ERROR_ENTITY_EXISTS); 
    } 
    return $valid; 

    } 
} 

用於Zend_Form的(其中有像上面的抽象類的EM()方法)的情況下:

/** 
    * Overrides superclass method to add just-in-time validation for NoEntityExists-type validators that 
    * rely on knowing the id of the entity in question. 
    * @param type $data 
    * @return type 
    */ 
    public function isValid($data) { 
    $unameUnique = new NoEntityExists(
        array('entityManager' => $this->em(), 
         'class' => 'PMS\Entity\User', 
         'property' => 'username', 
         'exclude' => array(
          array('property' => 'id', 'value' => $this->getValue('id')) 
         ) 
        ) 
    ); 
    $unameUnique->setMessage('Another user already has username "%value%"', NoEntityExists::ERROR_ENTITY_EXISTS); 

    $this->getElement('username')->addValidator($unameUnique); 

    return parent::isValid($data); 
} 
+0

感謝兩位響應者 - 我最終使用了一個timdev代碼的變體來用於我的驗證要求。 – cantera