2012-02-19 55 views
4

我有一個包含一個文件元素的Zend表單。Zend_Form_Element_File在不需要驗證時返回false

$this->addElement('file', 'image', array(
     'label'   => 'Upload Image:', 
     'destination' => APPLICATION_PATH . '/tmp/', 
     'validators' => array(
      array('count', true, array(
       'min' => 1, 
       'max' => 1, 
       'messages' => array(
        Zend_Validate_File_Count::TOO_FEW => 
         'You must upload an image file', 
        Zend_Validate_File_Count::TOO_MANY => 
         'You can only upload one image file'))), 
      array('extension', true, array(
       'extention' => 'jpg,png,gif', 
       'messages' => array(
        Zend_Validate_File_Extension::NOT_FOUND => 
         'The file has an invalid extention (jpg,png,gif only)', 
        Zend_Validate_File_Extension::FALSE_EXTENSION => 
         'The file has an invalid extention (jpg,png,gif only)'))), 
      array('imageSize', true, array(
       'minheight' => self::IMAGEHEIGHT, 
       'minwidth' => self::IMAGEWIDTH, 
       'maxheight' => self::IMAGEHEIGHT, 
       'maxwidth' => self::IMAGEWIDTH, 
       'messages' => array(
        Zend_Validate_File_ImageSize::HEIGHT_TOO_BIG => 
         'The image must be exactly ' . self::IMAGEHEIGHT . ' pixels tall', 
        Zend_Validate_File_ImageSize::HEIGHT_TOO_SMALL => 
         'The image must be exactly ' . self::IMAGEHEIGHT . ' pixels tall', 
        Zend_Validate_File_ImageSize::WIDTH_TOO_BIG => 
         'The image must be exactly ' . self::IMAGEWIDTH . ' pixels wide', 
        Zend_Validate_File_ImageSize::WIDTH_TOO_SMALL => 
         'The image must be exactly ' . self::IMAGEWIDTH . ' pixels wide', 
        Zend_Validate_File_ImageSize::NOT_DETECTED => 
         'The image dimensions cannot be detected', 
        Zend_Validate_File_ImageSize::NOT_READABLE => 
         'The image dimensions cannot be read')))) 
    )); 

該文件元素在後面的一段代碼中被設置爲不需要。當我提交沒有附加文件的表單時,表單validtion返回false,當我使用getErrors()方法查找表單錯誤時,也不報告錯誤。如果我提交附件的表單一切正常。

我一直在谷歌這一段時間,但無法找到答案。我希望有人能夠澄清爲什麼會發生這種情況,我正在使用ZF 1.11.11。

在此先感謝。

加里

編輯

下面是一些代碼樣本的要求。

這些是我用來驗證表單的方法。我已將標記的代碼標記爲驗證錯誤的解決方法。

public function formValid(Array $params) 
{ 
    if (is_null($this->_form)) 
     throw new Zend_Exception('You must first initialize the form'); 

    $formValid = $this->_validateForm($this->_form, $params); 

    // Workaround for bug in validating file elements 
    if (!$formValid) { 
     if (!$this->_form->getMessages()) { 
      $formValid = true; 
      $this->_validValues = $this->_form->getValidValues($params); 
     } 
    } 

    if ($formValid) { 
     if ($this->_form instanceof Admin_Form_AddDirectSite || 
      $this->_form instanceof Admin_Form_EditDirectSite) { 
       if (isset($this->_validValues['replaceImage'])) { 
        return $this->_form->getElement('image')->receive(); 
       } else { 
        return true; 
       } 
      } elseif ($this->_form instanceof Admin_Form_PromoteDirectSite) { 
       $today = new Zend_Date(); 
       $expires = new zend_date($this->_validValues['DirectSitesHighlighted']['toDate']); 
       if ($expires->isEarlier($today)) { 
        $this->_form->getSubForm('DirectSitesHighlighted') 
           ->getElement('toDate') 
           ->addError('The date must be in the future'); 
        return false; 
       } else { 
        return true; 
       } 
      } else { 
       return true; 
      } 
    } else { 
     return false; 
    } 
} 

protected function _validateForm(Zend_Form $form, Array $params) 
{ 
    if ($form->isValid($params)) { 
     $this->_validValues = $form->getValidValues($params); 
     return true; 
    } else { 
     $this->_validValues = null; 
     return false; 
    } 
} 

這些是我用來初始化表單的函數,有兩個表單類共享一個抽象類。

public function initAddForm() 
{ 
    $this->_form = new Admin_Form_AddDirectSite(); 
    return $this; 
} 

public function initEditForm() 
{ 
    $this->_form = new Admin_Form_EditDirectSite(); 
    return $this; 
} 

而這些是三種形式類。

class Admin_Form_AddDirectSite extends Admin_Form_DirectSites_Abstract 
{ 
    public function init() 
    { 
     parent::init(); 

     $this->setAction('/admin/direct-sites/add'); 

     $this->setDecorators(array(
      array('ViewScript', array('viewScript' => 'forms/addDirectSites.phtml')) 
     )); 

     $this->getElement('image')->setRequired(true); 

     $this->addElement('hidden', 'replaceImage', array(
      'required'  => true, 
      'label'   => 'Replace Image:', 
      'value'   => 1, 
      'filters'  => array('Int'), 
     )); 
    } 
} 

class Admin_Form_EditDirectSite extends Admin_Form_DirectSites_Abstract 
{ 
    public function init() 
    { 
     parent::init(); 

     $this->setAction('/admin/direct-sites/edit'); 

     $this->setDecorators(array(
      array('ViewScript', array('viewScript' => 'forms/editDirectSites.phtml')) 
     )); 

     $this->getElement('image')->setRequired(false); 

     $this->addElement('checkbox', 'replaceImage', array(
      'required'  => false, 
      'label'   => 'Replace Image:', 
      'checked'  => false, 
      'attribs'  => array(
       'title'   => 'Click to replace the image file' 
      ), 
      'filters'  => array('Int'), 
      'validators' => array(
       array('Int', true, array(
        'messages' => array(
         Zend_Validate_Int::NOT_INT => 
          'You must check to replace the image file')))) 
     )); 

     $this->addElement('hidden', 'directSiteId', array(
      'required' => false, 
      'vslue'  => null 
     )); 
    } 
} 

abstract class Admin_Form_DirectSites_Abstract extends Freedom_Zend_Form 
{ 
    /** 
    * Domain prefix http://www. 
    * @var integer 
    */ 
    const HTTPWWW = 1; 

    /** 
    * Domain prefix http:// 
    * @var integer 
    */ 
    const HTTP = 2; 

    /** 
    * The image width in pixels 
    * @var integer 
    */ 
    const IMAGEWIDTH = 100; 

    /** 
    * The image height in pixels 
    * @var integer 
    */ 
    const IMAGEHEIGHT = 100; 

    /** 
    * Initialize the form 
    * @see Zend_Form::init() 
    */ 
    public function init() 
    { 
     $domainPrefix = array(
      self::HTTPWWW => 'http://www.', 
      self::HTTP  => 'http;//' 
     ); 

     $genres = Model_Doctrine_GenresTable::getInstance()->getAllKeyPairs(); 

     $artworkMediums = Model_Doctrine_ArtworkMediumsTable::getInstance()->getAllKeyPairs(); 

     $this->setName('directSitesForm') // setup registration form 
      ->setAttrib('id', 'directSitesForm') 
      ->setMethod('post') 
      ->setAttrib('class', 'directSitesForm') 
      ->setEnctype(Zend_Form::ENCTYPE_MULTIPART); 

     $this->addElementPrefixPath('Freedom_Zend', 'Freedom/Zend'); // add element prefix path 
     $this->addPrefixPath('Freedom_Zend_Form', 'Freedom/Zend/Form'); // add form prefix path 

     $directSitesDescription = new Zend_Form_SubForm(); 
     $directSitesTitle = new Zend_Form_SubForm(); 

     $this->addElement('text', 'domainName', array(
      'required' => true, 
      'label'  => 'Domain Name:', 
      'attribs' => array(
       'title'  => 'Please enter the url of the site', 
       'size'  => 20, 
       'maxlength' => 255 
      ), 
      'filters'  => array('StringTrim', 'StripTags', 'StripNewlines'), 
      'validators' => array(
       array('NotEmpty', true, array(
         'messages' => array(
          Zend_Validate_NotEmpty::IS_EMPTY => 
           "You must specify the domain name"))), 
       array('StringLength', true, array(
         'min' => 5, 
         'max' => 255, 
         'messages' => array(
          Zend_Validate_StringLength::INVALID => 
           'Your URL must be between 5 and 255 characters in length', 
          Zend_Validate_StringLength::TOO_LONG => 
           'Your URL must not contain more than 255 characters', 
          Zend_Validate_StringLength::TOO_SHORT => 
           'Your URL must contain more than 5 characters')))) 
     )); 

     $this->addElement('radio', 'websitePrefix', array(
      'required' => true, 
      'label'  => 'Domain Prefix:', 
      'attribs' => array(
       'title'  => 'Please select the URL prefix for the domain name' 
      ), 
      'multiOptions' => $domainPrefix, 
      'value'  => self::HTTPWWW, 
      'filters' => array('int'), 
      'validators' => array(
       array('NotEmpty', true, array(
        'messages' => array(
         Zend_Validate_NotEmpty::IS_EMPTY => 
          "You must select your agency's website URL", 
         Zend_Validate_NotEmpty::INVALID => 
          "You must select your agency's website URL"))), 
       array('InArray', true, array(
        'haystack' => array_keys($domainPrefix), 
        'messages' => array(
         Zend_Validate_InArray::NOT_IN_ARRAY => 
          "You must select your agency's website URL")))) 
     )); 

     $directSitesTitle->addElement('text', 'title', array(
      'required' => true, 
      'label'  => 'Title:', 
      'attribs' => array(
       'title'  => 'Please enter the name of the site', 
       'size'  => 20, 
       'maxlength' => 255 
      ), 
      'filters'  => array('StringTrim', 'StripTags', 'StripNewlines'), 
      'validators' => array(
       array('NotEmpty', true, array(
         'messages' => array(
          Zend_Validate_NotEmpty::IS_EMPTY => 
           "You must specify the sites title"))), 
       array('StringLength', true, array(
         'min' => 5, 
         'max' => 100, 
         'messages' => array(
          Zend_Validate_StringLength::INVALID => 
           'Your title must be between 5 and 100 characters in length', 
          Zend_Validate_StringLength::TOO_LONG => 
           'Your title must not contain more than 100 characters', 
          Zend_Validate_StringLength::TOO_SHORT => 
           'Your title must contain more than 5 characters')))) 
     )); 

     $directSitesDescription->addElement('text', 'description', array(
      'required' => true, 
      'label'  => 'Description:', 
      'attribs' => array(
       'title'  => 'Please enter the description of the site', 
       'size'  => 50, 
       'maxlength' => 100 
      ), 
      'filters'  => array('StringTrim', 'StripTags', 'StripNewlines'), 
      'validators' => array(
       array('NotEmpty', true, array(
         'messages' => array(
          Zend_Validate_NotEmpty::IS_EMPTY => 
           "You must specify the sites description"))), 
       array('StringLength', true, array(
         'min' => 5, 
         'max' => 100, 
         'messages' => array(
          Zend_Validate_StringLength::INVALID => 
           'Your sites description must be between 5 and 100 characters in length', 
          Zend_Validate_StringLength::TOO_LONG => 
           'Your sites description must not contain more than 100 characters', 
          Zend_Validate_StringLength::TOO_SHORT => 
           'Your sites description must contain more than 5 characters')))) 
     )); 

     $this->addElement('file', 'image', array(
      'label'   => 'Upload Image:', 
      'destination' => APPLICATION_PATH . '/tmp/', 
      'validators' => array(
       array('count', true, array(
        'min' => 0, 
        'max' => 1, 
        'messages' => array(
         Zend_Validate_File_Count::TOO_FEW => 
          'You must upload an image file', 
         Zend_Validate_File_Count::TOO_MANY => 
          'You can only upload one image file'))), 
       array('extension', true, array(
        'extention' => 'jpg,png,gif', 
        'messages' => array(
         Zend_Validate_File_Extension::NOT_FOUND => 
          'The file has an invalid extention (jpg,png,gif only)', 
         Zend_Validate_File_Extension::FALSE_EXTENSION => 
          'The file has an invalid extention (jpg,png,gif only)'))), 
       array('imageSize', true, array(
        'minheight' => self::IMAGEHEIGHT, 
        'minwidth' => self::IMAGEWIDTH, 
        'maxheight' => self::IMAGEHEIGHT, 
        'maxwidth' => self::IMAGEWIDTH, 
        'messages' => array(
         Zend_Validate_File_ImageSize::HEIGHT_TOO_BIG => 
          'The image must be exactly ' . self::IMAGEHEIGHT . ' pixels tall', 
         Zend_Validate_File_ImageSize::HEIGHT_TOO_SMALL => 
          'The image must be exactly ' . self::IMAGEHEIGHT . ' pixels tall', 
         Zend_Validate_File_ImageSize::WIDTH_TOO_BIG => 
          'The image must be exactly ' . self::IMAGEWIDTH . ' pixels wide', 
         Zend_Validate_File_ImageSize::WIDTH_TOO_SMALL => 
          'The image must be exactly ' . self::IMAGEWIDTH . ' pixels wide', 
         Zend_Validate_File_ImageSize::NOT_DETECTED => 
          'The image dimensions cannot be detected', 
         Zend_Validate_File_ImageSize::NOT_READABLE => 
          'The image dimensions cannot be read')))) 
     )); 

     $this->addElement('multiCheckbox', 'Genres', array(
      'required' => false, 
      'label'  => 'Genres:', 
      'attribs' => array(
       'title'  => 'Please select the sites genres' 
      ), 
      'multiOptions' => $genres, 
      'filters' => array('int'), 
      'validators' => array(
       array('NotEmpty', true, array(
        'messages' => array(
         Zend_Validate_NotEmpty::IS_EMPTY => 
          "You must select the sites genres", 
         Zend_Validate_NotEmpty::INVALID => 
          "You must select the sites genres"))), 
       array('InArray', true, array(
        'haystack' => array_keys($genres), 
        'messages' => array(
         Zend_Validate_InArray::NOT_IN_ARRAY => 
          "You must select the sites genres")))) 
     )); 

     $this->addElement('multiCheckbox', 'ArtworkMediums', array(
      'required' => false, 
      'label'  => 'Artwork Mediums:', 
      'attribs' => array(
       'title'  => 'Please select the sites artwork mediums' 
      ), 
      'multiOptions' => $artworkMediums, 
      'filters' => array('int'), 
      'validators' => array(
       array('NotEmpty', true, array(
        'messages' => array(
         Zend_Validate_NotEmpty::IS_EMPTY => 
          "You must select the sites artwork mediums", 
         Zend_Validate_NotEmpty::INVALID => 
          "You must select the sites artwork mediums"))), 
       array('InArray', true, array(
        'haystack' => array_keys($artworkMediums), 
        'messages' => array(
         Zend_Validate_InArray::NOT_IN_ARRAY => 
          "You must select the sites artwork mediums")))) 
     )); 

     $this->addElement('submit', 'save', array(
      'label' => 'Save', 
      'attribs' => array(
       'title' => 'Save') 
     )); 

     $this->addSubForm($directSitesDescription, 'DirectSitesDescription') 
      ->addSubForm($directSitesTitle, 'DirectSitesTitle'); 
    } 
} 
+1

我有同樣的問題,因爲你,但只有一種形式。由於這篇文章有點老,你找到了解決方案嗎? – 2012-05-22 10:27:05

回答

1

所有我能看到的是,你的'count'驗證看起來有點靠不住的,它看起來像你需要在任何時候都至少1個文件。至於爲什麼沒有錯誤信息,我不知道。
可以嘗試設置'min' => 0

array('count', true, array(
       'min' => 1, 
       'max' => 1, 
       'messages' => array(
        Zend_Validate_File_Count::TOO_FEW => 
         'You must upload an image file', 
        Zend_Validate_File_Count::TOO_MANY => 
         'You can only upload one image file'))), 

下面是Zend_Validate_File_Count構造函數的API,看到整個API在ZF 1.11 API

__construct(整數|陣列| \ Zend_Config的$選項):void設置驗證選項

最小限制文件計數,當與max = null一起使用時,它是最大值 文件計數它也接受帶'min'和'max'鍵的數組如果 $ options是一個整數,它將用作最大文件數量因爲Array 可以接受以下鍵:'min':最小文件計數'max':最大 filecount參數名稱類型說明 $ options integer | array | \ Zend_Config該適配器

+0

嗨RockyFord,感謝您的回覆。我試圖按照您的建議將min設置爲零,但沒有運氣,驗證仍然失敗並且沒有錯誤。 – Garry 2012-02-19 12:20:16

0

RockyFord是正確的選擇,你應該就算是不需要的元素Count驗證的min值設置爲0

,當值不爲空的驗證仍然處理。文件元素與計數驗證器有點不同。如果您指定大於0的min,它仍然會要求上傳許多文件。

嘗試以下代碼,關閉所需的標誌。另外,我們將設置Count驗證器至少需要0個文件。

$form->getElement('image') 
    ->setRequired(false) 
    ->getValidator('count') 
    ->setMin(0); 

我測試了這個,它工作。如果我沒有將min設置爲0,則表單將無法通過驗證,但是,我會看到一條錯誤消息,內容爲You must upload an image file。也許你的裝飾器沒有在文件元素上顯示錯誤?

+0

嗨drew010,謝謝你的回答。正如我上面所說,我已經根據RockyFord的建議將min設置爲零,但是當我不上傳文件時,仍然會出現驗證錯誤。 Zend形式的getMessages()方法返回一個空數組,因此不會在內部報告錯誤。 – Garry 2012-02-19 21:45:08

+0

好的,在那種情況下,你可以在你的表單和控制器的使用位置發佈更完整的代碼嗎?你是否在你的視圖中單獨渲染表單元素?如果是這樣,也許你留下了一個元素?將min設置爲0應該可以工作。你是在多個地方調用isValid還是你自己驗證一個元素,或者在表單或元素上調用'markAsError'或'addError'? – drew010 2012-02-19 22:26:22

+0

我在上面添加了一些更多的代碼示例,顯示了我使用的驗證方法以及表單本身。有兩種形式共享一個抽象類,其中一個在文件元素上設置爲true,所以我期望Admin_Form_AddDirectSite驗證失敗。另外,如果我從文件元素中刪除所有驗證器,驗證仍然失敗。 – Garry 2012-02-20 12:44:52

1

仔細檢查,以確保

enctype='multipart/form-data' 

包含在HTML表單元素。我花了兩個小時處理同樣的問題。原來,這是我的問題。

+0

嗨Liz,謝謝你的回答。我的表單enctype是正確的(multipart/form-data) – Garry 2012-08-10 20:15:58

1

ZF 1.11 一個更簡單的解決方案是在提交表單要刪除的元素:

$upload = new Zend_File_Transfer(); 
    $files = $upload->getFileInfo(); 

     if(empty($files)) 
     { 
      $form->removeElement('image_name'); 
     } 
     else 
     { 
      $form->image_name->receive(); 
     } 

     if($form->isValid($_POST)) 
     { 
     $formData = $form->getValues(); 
     } 
相關問題