Zend Framework: требуется одно из трех значений - PullRequest
3 голосов
/ 13 июля 2011

Для моего школьного проекта я работаю над приложением для управления базами данных.Это мое первое настоящее приложение Zend Framework.

Сейчас, прямо сейчас, я установил 3 значения: почтовый индекс, адрес электронной почты и телефон.Они требуются следующим образом (Пример):

        $mail = $this->createElement('text', 'mail');
    $mail->setLabel('E-mail:')
            ->setAttrib('size', 50)->addValidator('StringLength', false, array(6, 40))->addValidator('EmailAddress', true)
            ->setRequired(true);
        $telephone = $this->createElement('text', 'telephone');
    $telephone->setLabel('Telephone:')
            ->setAttrib('size', 50)->addValidator('StringLength', false, array(10, 10))
            ->setRequired(true);

Как сделать только один из них обязательным?

Я работаю с Zend_Form, а также работаю с группами отображения.

Есть ли кто-нибудь, кто знает решение для моей программы?Может быть, использовать массив?

Заранее спасибо,

JorritK

ОБНОВЛЕНИЕ

@brady.vitrano

Хорошо, первая часть моего кода выглядит следующим образом:

<?php

class Application_Form_Validate_ContactMethodSelected
extends Zend_Validate_Abstract
{
const INVALID = 'invalid';

protected $_messageTemplates = array(
    self::INVALID => 'Must select at least one contact method'
);

public function isValid($value, $context = array())
{
     // You need to use your element names, consider making these dynamic
    $checkFields = array('telefoon','mobiel','mail');
    // Check if all are empty
    foreach ( $checkFields as $field ) {
        if (isset($context[$field]) && !empty($context[$field])) {
            // Only one value needs to return true..skip the rest
            return true;
        }
    }

    // All were empty, set your own error message
    $this->_error(self::INVALID);
    return false;
}

}

class Application_Form_Nieuwkandidaat extends Zend_Form
{

public function init()
{
     $this->setMethod('post');
    $DB = Zend_Db_Table::getDefaultAdapter();


    $telefoon = $this->createElement('text', 'telefoon');
    $telefoon->setLabel('Telefoon:')
            ->setAttrib('size', 50)->addValidator('StringLength', false,array(10,10));
    $telefoon->addValidator(new Application_Form_Validate_ContactMethodSelected());
    $mobiel = $this->createElement('text', 'mobiel');
    $mobiel->setLabel('Mobiel:')
            ->setAttrib('size', 50)->addValidator('StringLength', false,array(10,10));
    $mobiel->addValidator(new Application_Form_Validate_ContactMethodSelected());
    $mail = $this->createElement('text', 'mail');
    $mail->setLabel('E-mail:')
            ->setAttrib('size', 50)->addValidator('StringLength', false,array(6,40))->addValidator('EmailAddress', true);
    $mail->addValidator(new Application_Form_Validate_ContactMethodSelected());

Оно не будет отображать сообщение после нажатия кнопки отправки.Что еще я должен изменить?Спасибо за помощь!

Ответы [ 4 ]

13 голосов
/ 13 июля 2011

Хорошее решение для рассмотрения - написать собственный валидатор для элементов.

В вашем методе isValid вы должны будете проверить на основе $context других значений. Что-то вроде:

EDIT

/** /library/Application/Form/Validate/ContactMethodSelected.php **/

class Application_Form_Validate_ContactMethodSelected 
    extends Zend_Validate_Abstract
{
    const INVALID = 'invalid';

    protected $_messageTemplates = array(
        self::INVALID => 'Must select at least one contact method'
    ); 

    public function isValid($value, $context = array())
    {
         // You need to use your element names, consider making these dynamic
        $checkFields = array('phone','email','address');
        // Check if all are empty
        foreach ( $checkFields as $field ) {
            if (isset($context[$field]) && !empty($context[$field])) {
                // Only one value needs to return true..skip the rest
                return true;
            }
        }

        // All were empty, set your own error message
        $this->_error(self::INVALID);
        return false;   
    }

}

Теперь вы должны указать элементам использовать этот валидатор. Итак, внесите изменения в свои формы init() метод.

 $mail->addValidator(new Application_Form_Validate_ContactMethodSelected());
 $telephone->addValidator(new Application_Form_Validate_ContactMethodSelected());

Не забудьте: После того, как вы получите свой собственный валидатор, вам придется удалить isRequired() с каждого элемента.

EDIT2

Вы должны установить пользовательский валидатор в качестве первого валидатора в цепочке и прервать работу при ошибке. Кроме того, вы должны setAllowEmpty() в ложь.

$telefoon = $this->createElement('text', 'telefoon');
$telefoon->setLabel('Telefoon:')
        ->setAttrib('size', 50)->setAllowEmpty(false)
        ->addValidator(new Application_Form_Validate_ContactMethodSelected(),true)
        ->addValidator('StringLength', false,array(10,10));
$mobiel = $this->createElement('text', 'mobiel');
$mobiel->setLabel('Mobiel:')
        ->setAttrib('size', 50)->setAllowEmpty(false)
        ->addValidator(new Application_Form_Validate_ContactMethodSelected(),true)
        ->addValidator('StringLength', false,array(10,10));
$mail = $this->createElement('text', 'mail');
$mail->setLabel('E-mail:')
        ->setAttrib('size', 50)->setAllowEmpty(false)
        ->addValidator(new Application_Form_Validate_ContactMethodSelected(),true)
        ->addValidator('StringLength', false,array(6,40))->addValidator('EmailAddress', true);

Далее вам необходимо обновить метод isValid следующим образом:

public function isValid($value, $context = array())
{
    // You need to use your element names, consider making these dynamic
    $checkFields = array('telefoon','mobiel','mail');
    // Check if all are empty
    foreach ( $checkFields as $field ) {
    if (isset($context[$field]) && !empty($context[$field])) {

        if (!empty($value)) {
            // This is the element with content... validate as true
            return true;
        }
        // we are going to return false and no error
        // to break validation chain on other empty values
        // This is a quick hack, don't have time to invest in this
        return false;
        }
    }

    // All were empty, set your own error message
    $this->_error(self::INVALID);
    return false;
}

Теперь вам нужно добавить еще одно условие в ваш код, который использует этот валидатор. Мы должны требовать, чтобы в форме не было сообщений об ошибках.

if ($form->isValid($_POST) || !count($form->getMessages())) {
    /** Valid, now you can process **/
} else {
    /** Not valid **/
}
3 голосов
/ 11 ноября 2011

Я думаю, что лучший подход - самый простой.Вам не нужно писать никаких пользовательских валидаторов.Вам просто нужно проверить, не отображается ли одно из обязательных значений как непустое после проверки формы, потому что тогда у вас будет доступ к отфильтрованным и проверенным значениям формы.

if ($form->isValid($_POST)) {

    // get filtered and validated form values
    $params = $form->getValues();

    // check if there is a selected contact method
    if (isContactMethodSelected ($params)) {
       // the form is Valid!

    } else {
       // not valid
    }


} else {
    // not valid
}

Вот "isContactMethodSelected"метод.Вы можете просто добавить его в текущий класс контроллера.

private function isContactMethodSelected ($params) {

        // define array with the contact methods as they appear in the $params as keys
        $checkFields = array('telefoon','mobiel','mail');

        // check if there is at least one contact method selected
        foreach ($checkFields as $field) {
            if (isset($params[$field]) && !empty($params[$field])) {
                return true;
            }
        }

        return false;
    }
1 голос
/ 11 ноября 2011

Я думаю, что самое простое и быстрое решение - переопределить функцию isValid для самой формы

class Application_Form_Nieuwkandidaat extends Zend_Form
{

    //...

    public function isValid($data)
    {
        $valid = parent::isValid($data);
        if ( ! $data['mail'] && ! $data['telephone'] && ! $data['postcode'] ){
            $this->addError('Please supply one of email, telephone or postcode');
            $valid = false;
        }
        return $valid;
    }

    //...

}

Одна маленькая функция, связанная с формой, простая для понимания, вряд ли потерпит неудачу, вряд либыть источником трудных ошибок.

0 голосов
/ 13 июля 2011

Удалить

$foo->setRequired();

метод из двух, который вы не хотите устанавливать как требуется ....

$telephone->setLabel('Telephone:')
          ->setAttrib('size', 50)
          ->addValidator('StringLength', false, array(10, 10))
          ->setRequired(true);

становится

$telephone->setLabel('Telephone:')
          ->setAttrib('size', 50)
          ->addValidator('StringLength', false, array(10, 10));
...