Zend_Form_Element_File在不需要时在验证时返回false

时间:2012-02-19 00:03:39

标签: zend-framework zend-form zend-form-element

我有一个Zend表单,其中包含一个文件元素。

    $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');
    }
}

5 个答案:

答案 0 :(得分: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,请参阅ZF 1.11 API处的整个API

  

__ construct(integer | array | \ Zend_Config $ options):void设置验证器选项

     

Min限制文件计数,当与max = null一起使用时,它是最大值   文件计数它还接受一个键为'min'和'max'的数组   $ options是一个整数,它将被用作最大文件数As Array   接受以下键:'min':最小文件数'max':最大值   filecount参数名称类型描述   $ options integer | array | \ Zend_Config适配器选项

答案 1 :(得分:1)

仔细检查以确保

enctype='multipart/form-data'

包含在html表单元素中。我花了两个小时同样的问题。事实证明这是我的问题。

答案 2 :(得分:0)

RockyFord是正确的,您应该将min验证程序的Count值设置为0。

即使不需要元素,当值不为空时,仍会处理其验证器。文件元素与计数验证器的工作方式略有不同。如果指定min大于0,则仍需要上传许多文件。

请在关闭所需标志的位置尝试以下代码。另外,我们将Count验证器设置为至少需要0个文件。

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

我对此进行了测试并且有效。如果我没有将min设置为0,表单将无法验证,但是,我会看到一条错误消息,显示You must upload an image file。也许您的装饰器没有在File元素上显示错误?

答案 3 :(得分:0)

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

答案 4 :(得分:0)

在类isValid派生的类中覆盖方法Zend_Form

/**
 * Class Custom_Form
 */
class Custom_Form extends Zend_Form
{
    // [...]

    /**
     * Validate the form
     *
     * @param  array $data
     * @throws Zend_Form_Exception
     * @return bool
     */
    public function isValid($data)
    {
        /** @var Zend_Form_Element_File $file */
        $file = $this->getElement('file');

        /**
         * Remember the validators we set before
         */
        $validators = $file->getValidators();

        /**
         * Remove validators if field is empty
         */
        if (empty($_FILES['file']['name'])) {
            $file->removeValidator('Extension');
        }

        /**
         * Run validation
         */
        $isValid = parent::isValid($data);

        /**
         * Set back the original validators after validation
         */
        $file->setValidators($validators);

        return $isValid;
    }

    // [...]
}