Zend_Form_Element_File возвращает false при проверке, когда не требуется - PullRequest
5 голосов
/ 19 февраля 2012

У меня есть Zend Form, содержащая один элемент файла среди других.

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

Этот элемент файла установлен как необязательный в более позднем фрагменте кода.Когда я отправляю форму без вложенного файла, проверка правильности формы возвращает 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 ]

1 голос
/ 09 августа 2012

Дважды проверьте, чтобы убедиться, что

enctype='multipart/form-data'

включено в элемент формы html.Я провел два часа с той же проблемой.Оказывается, это была моя проблема.

1 голос
/ 19 февраля 2012

Все, что я могу видеть, это то, что ваш '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'))),

Ниже представлен API для конструктора Zend_Validate_File_Count, см. Весь API на API ZF 1.11

__ construct (integer | array | \ Zend_Config $ options): void Устанавливает параметры валидатора

Min ограничивает количество файлов, при использовании с max = null это максимум Количество файлов. Также принимает массив с ключами min и max. Если $ options - это целое число, оно будет использоваться как максимальное количество файлов в качестве массива. is принимает следующие ключи: 'min': минимальное количество файлов 'max': максимальное filecount Параметры Имя Тип Описание $ options integer | array | \ Zend_Config Опции для адаптера

0 голосов
/ 15 марта 2019

Переопределить метод 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;
    }

    // [...]
}
0 голосов
/ 23 октября 2012

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();
       }
0 голосов
/ 20 февраля 2012

RockyFord верен, вы должны установить значение min валидатора Count равным 0.

Даже если элемент не требуется, его валидаторы все еще обрабатываются, когда значение не пустое.Файловые элементы работают немного иначе с валидатором count.Если вы укажете min больше 0, все равно потребуется загрузить много файлов.

Попробуйте следующий код, чтобы отключить требуемый флаг.Кроме того, мы установим для валидатора Count как минимум 0 файлов.

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

Я проверил это, и это сработало.Если бы я не установил min на 0, форма не прошла бы проверку, однако я бы увидел сообщение об ошибке, читающее You must upload an image file.Возможно, ваши декораторы не показывают ошибку в элементах File?

...