2011-07-29 57 views
2

表單中有一個多選元素。需要驗證其中選擇了多少項目(最小值和最大值)。Zend驗證多選值

問題是,當元素可以有多個值時,每個值分別驗證。

我試圖設置isArrayfalse來驗證我的自定義驗證ArraySize值,但新的問題出現了:整個陣列的值傳遞給InArray驗證和驗證失敗。所以我不得不通過將registerInArrayValidator設置爲false來關閉它。

現在我可以驗證所選值的數量的值,但不能驗證它們與提供的選項的對應關係。

有沒有辦法解決這個問題而不創建一個更多的自定義驗證器?

+2

我認爲解決的辦法是一個自定義的驗證程序的創建: http://framework.zend.com/manual/en/zend.validate.writing_validators.html – JellyBelly

回答

-1

儘管無需編寫自定義驗證程序即可輕鬆完成,但如果您需要做一些與衆不同的事情,那麼編寫一個程序就沒什麼問題。

這聽起來像是其中一種情況。

+0

真的沒有錯,但我沒有看到寫我的自定義驗證器(驗證整個數組)的方式,可以可以與其他標準或非標準驗證器一起重新使用(即驗證e分開排列數組中的每個元素)。 對於cource,我最初的任務可以通過編寫自定義驗證器來解決,但我想知道一些更常見的問題。 –

0

注:我認爲這是Zend的1

我可以看到這樣做是爲了延長複選和使用自定義的isValid的唯一方法。通過這種方式,您可以一次查看完整的值數組,而不僅僅是一個值。

下面是我的自定義多選類

<?php 
/** 
* My_MinMaxMultiselect 
*/ 
class My_MinMaxMultiselect extends Zend_Form_Element_Multiselect 
{ 
    /** 
    * Validate element contains the correct number of 
    * selected items. Check value against minValue/maxValue 
    * 
    * @param mixed $value 
    * @param mixed $context 
    * @return boolean 
    */ 
    public function isValid($value, $context = null) 
    { 
     // Call Parent first to cause chain and setValue 
     $parentValid = parent::isValid($value, $context); 

     $valid = true; 

     if ((('' === $value) || (null === $value)) 
      && !$this->isRequired() 
      && $this->getAllowEmpty() 
     ) { 
      return $valid; 
     } 

     // Get All Values 
     $minValue = $this->getMinValue(); 
     $maxValue = $this->getMaxValue(); 

     $count = 0; 
     if (is_array($value)) { 
      $count = count($value); 
     } 

     if ($minValue && $count < $minValue) { 
      $valid = false; 
      $this->addError('The number of selected items must be greater than or equal to ' . $minValue); 
     } 

     if ($maxValue && $count > $maxValue) { 
      $valid = false; 
      $this->addError('The number of selected items must be less than or equal to ' . $maxValue); 
     } 

     return ($parentValid && $valid); 
    } 

    /** 
    * Get the Minimum number of selected values 
    * 
    * @access public 
    * @return int 
    */ 
    public function getMinValue() 
    { 
     return $this->getAttrib('min_value'); 
    } 

    /** 
    * Get the Maximum number of selected values 
    * 
    * @access public 
    * @return int 
    */ 
    public function getMaxValue() 
    { 
     return $this->getAttrib('max_value'); 
    } 

    /** 
    * Set the Minimum number of selected Values 
    * 
    * @param int $minValue 
    * @return $this 
    * @throws Bad_Exception 
    * @throws Zend_Form_Exception 
    */ 
    public function setMinValue($minValue) 
    { 
     if (is_int($minValue)) { 
      if ($minValue > 0) { 
       $this->setAttrib('min_value', $minValue); 
      } 

      return $this; 
     } else { 
      throw new Bad_Exception ('Invalid value supplied to setMinValue'); 
     } 
    } 

    /** 
    * Set the Maximum number of selected values 
    * 
    * @param int $maxValue 
    * @return $this 
    * @throws Bad_Exception 
    * @throws Zend_Form_Exception 
    */ 
    public function setMaxValue($maxValue) 
    { 
     if (is_int($maxValue)) { 
      if ($maxValue > 0) { 
       $this->setAttrib('max_value', $maxValue); 
      } 

      return $this; 
     } else { 
      throw new Bad_Exception ('Invalid value supplied to setMaxValue'); 
     } 
    } 

    /** 
    * Retrieve error messages and perform translation and value substitution. 
    * Overridden to avoid errors from above being output once per value 
    * 
    * @return array 
    */ 
    protected function _getErrorMessages() 
    { 
     $translator = $this->getTranslator(); 
     $messages = $this->getErrorMessages(); 
     $value = $this->getValue(); 
     foreach ($messages as $key => $message) { 
      if (null !== $translator) { 
       $message = $translator->translate($message); 
      } 
      if (($this->isArray() || is_array($value)) 
       && !empty($value) 
      ) { 
       $aggregateMessages = array(); 
       foreach ($value as $val) { 
        $aggregateMessages[] = str_replace('%value%', $val, $message); 
       } 
       // Add additional array unique to avoid the same error for all values 
       $messages[$key] = implode($this->getErrorMessageSeparator(), array_unique($aggregateMessages)); 
      } else { 
       $messages[$key] = str_replace('%value%', $value, $message); 
      } 
     } 

     return $messages; 
    } 
} 

要使用此的形式,其中用戶必須選擇正好3個選項:

$favouriteSports = new MinMaxMultiselect('favourite_sports'); 
    $favouriteSports 
     ->addMultiOptions(array(
      'Football', 
      'Cricket', 
      'Golf', 
      'Squash', 
      'Rugby' 
     )) 
     ->setRequired() 
     ->setLabel('Favourite Sports') 
     ->setMinValue(3) 
     ->setMaxValue(3);