2013-01-22 23 views
2

我創建了一個自定義驗證程序,要求填寫「門牌號」或「單位號」,但不能同時填寫(XOR)。ZF2 - 驗證程序鏈不在空元素上運行

如果兩個字段都已填寫(失敗),或者已填寫(通過),則驗證程序正常工作。但是如果兩個字段都是空的,驗證器根本不運行。

下面是兩個元素的輸入濾波器規格:

$input = new Input('flat_number'); 
$input->setRequired(true); 
$input->setAllowEmpty(true); 
$input->setValue($this->flatNumber); 
$input->getValidatorChain() 
     ->addValidator(new \Si\Validator\HouseFlatCheck('house_number')) 
     ->addValidator(new \Zend\Validator\StringLength(array('max' => 30))); 
$input->getFilterChain()->attach($this->defaultFilterChain); 
$inputFilter->add($input); 

$input = new Input('house_number'); 
$input->setRequired(true); 
$input->setAllowEmpty(true); 
$input->setValue($this->houseNumber); 
$input->getValidatorChain() 
     ->addValidator(new \Si\Validator\HouseFlatCheck('flat_number')) 
     ->addValidator(new \Zend\Validator\StringLength(array('max' => 30))); 
$input->getFilterChain()->attach($this->defaultFilterChain); 
$inputFilter->add($input); 

通過對事物的外表,如果該字段爲空,並傳遞「需要」和「allowEmpty」要求驗證不運行。

有沒有什麼辦法可以讓'HouseFlatCheck'驗證器對我的兩個元素運行,儘管這兩個字段都是空的?

回答

3

經過了一整天的研究,我找到了解決問題的方法。

首先,在Zend \輸入過濾\ BaseInputFilter類包含了isValid()的以下內容:

public function isValid() 
{ 
    if (null === $this->data) { 
     throw new Exception\RuntimeException(sprintf(
      '%s: no data present to validate!', 
      __METHOD__ 
     )); 
    } 

    $this->validInputs = array(); 
    $this->invalidInputs = array(); 
    $valid    = true; 

    $inputs = $this->validationGroup ?: array_keys($this->inputs); 
    foreach ($inputs as $name) { 
     $input = $this->inputs[$name]; 
     if (!array_key_exists($name, $this->data) 
      || (null === $this->data[$name]) 
      || (is_string($this->data[$name]) && strlen($this->data[$name]) === 0) 
     ) { 
      if ($input instanceof InputInterface) { 
       // - test if input is required 
       if (!$input->isRequired()) { 
        $this->validInputs[$name] = $input; 
        continue; 
       } 
       // - test if input allows empty 
       if ($input->allowEmpty()) { 
        $this->validInputs[$name] = $input; 
        continue; 
       } 
      } 
      // make sure we have a value (empty) for validation 
      $this->data[$name] = ''; 
     } 

     if ($input instanceof InputFilterInterface) { 
      if (!$input->isValid()) { 
       $this->invalidInputs[$name] = $input; 
       $valid = false; 
       continue; 
      } 
      $this->validInputs[$name] = $input; 
      continue; 
     } 
     if ($input instanceof InputInterface) { 
      if (!$input->isValid($this->data)) { 
       // Validation failure 
       $this->invalidInputs[$name] = $input; 
       $valid = false; 

       if ($input->breakOnFailure()) { 
        return false; 
       } 
       continue; 
      } 
      $this->validInputs[$name] = $input; 
      continue; 
     } 
    } 

    return $valid; 
} 

至於allowEmpty是我的輸入條件爲真,該輸入驗證停止,並移動到下一個輸入數組中的元素。更改allowEmpty爲false,我的投入解決了這個問題,但創建另一個,作爲「Zend的\輸入過濾器\輸入」類調用期間,它的isValid()函數以下功能:

protected function injectNotEmptyValidator() 
{ 
    if ((!$this->isRequired() && $this->allowEmpty()) || $this->notEmptyValidator) { 
     return; 
    } 
    $chain = $this->getValidatorChain(); 

    // Check if NotEmpty validator is already first in chain 
    $validators = $chain->getValidators(); 
    if (isset($validators[0]['instance']) 
     && $validators[0]['instance'] instanceof NotEmpty 
    ) { 
     $this->notEmptyValidator = true; 
     return; 
    } 

    $chain->prependByName('NotEmpty', array(), true); 
    $this->notEmptyValidator = true; 
} 

因爲我是必填欄位allowEmpty現在是錯誤的,'NotEmpty'驗證器會自動添加到我的鏈中。一旦發現,解決方案很簡單。

namespace Si\InputFilter; 

class Input extends \Zend\InputFilter\Input { 
    protected function injectNotEmptyValidator() { 
     return; 
    } 
} 

做上述menas是一個「NotEmpty」不添加到我的校驗器鏈,所以我的XOR:我在自定義庫,它覆蓋了injectNotEmptyValidator功能,迫使它什麼也不做,創造了一個「輸入」類驗證程序可以正確運行。我現在要做的就是使用我更正的Si \ InputFilter \ Input類爲這兩個元素填充InputFilter。

希望有所幫助。

1

我會做這個不同︰我會創建一個自定義輸入,接受一個值的數組,代表房屋號碼和單位號碼。然後輸入將包含執行XOR邏輯的自定義驗證器,並且將基於哪個驗證鏈選擇合適的驗證鏈。 (類似地,在形式方面,我表示這是一個複合元件。)

+0

我認爲在再利用的觀點出發,覆蓋解決方案對我更好。我將需要運行稍後在我的應用程序中在字段(空或不空)上觸發的自定義驗證器。儘管非常感謝你的貢獻!完美的感覺! – MrNorm