Как создать валидатор, который зависит от нескольких значений для Zend_Form? - PullRequest
2 голосов
/ 07 ноября 2011

У меня есть форма с одним текстовым полем (для компании):

class Cas_Form_Company extends Zend_Form
{

    public function init()
    {
        $this->addElement('hidden', 'id');
        $this->addElement('text', 'name', array('label' => 'Name'));
        $this->addElement('submit', 'submit', array('label' => 'Create'));

        $name = $this->getElement('name');
        $name->addValidator('stringLength', false, array(2,45));
        $name->addValidator(new Cas_Model_Validate_CompanyUnique());

        $this->setMethod('post');
        $this->setAction(Zend_Controller_Front::getInstance()->getBaseUrl() . '/Company/Submit');
    }

    public function SetFromExistingCompany(Cas_Model_Company $company)
    {
        $this->getElement('id')->setValue($company->GetId());
        $this->getElement('name')->setValue($company->GetName());
        $this->getElement('submit')->setLabel('Edit');
        $this->addElement('submit', 'delete', array('label' => 'Delete', 'value' => 'delete'));
    }

    public function Commit()
    {
        if (!$this->valid())
        {
            throw new Exception('Company form is not valid.');
        }

        $data = $this->getValues();
        if (empty($data['id']))
        {
            Cas_Model_Gateway_Company::FindOrCreateByName($data['name']);
        }
        else
        {
            $company = Cas_Model_Gateway_Company::FindById((int)$data['id']);
            $company->SetName($data['name']);
            Cas_Model_Gateway_Company::Commit($company);
        }
    }
}

Я также создал небольшой валидатор, который заставляет компании иметь уникальные имена:

class Cas_Model_Validate_CompanyUnique extends Zend_Validate_Abstract
{
    protected $_messageTemplates = array(
        'exists' => '\'%value%\' is already a company.'
    );

    /**
     * @param string $value
     * @return bool
     */
    public function isValid($value)
    {
        $this->_setValue($value);
        $company = Cas_Model_Gateway_Company::FindByName($value);
        if ($company)
        {
            $this->_error('exists');
            return false;
        }

        return true;
    }
}

Теперь это прекрасно работает для создания новых компаний.Проблема возникает, когда я хочу разрешить редактирование компаний.Это связано с тем, что для операции редактирования, в то время как название компании должно быть уникальным, форма, содержащая имя, уже имеющее отношение к данному идентификатору, вообще не является правкой (и, следовательно, действительна).То есть форма действительна, если либо имя еще не существует в базе данных, либо данное имя совпадает с именем, уже присвоенным этому идентификатору.

Однако записать это как валидатор проблематичнопотому что валидатор получает только значение, с которым он работает, а не ID, о котором идет речь.

Как написать валидатор для такого рода вещей?

Ответы [ 2 ]

5 голосов
/ 07 ноября 2011

Вы можете использовать плохо документированный второй аргумент $context для isValid().

См. http://framework.zend.com/manual/en/zend.form.elements.html#zend.form.elements.validators и прокрутите вниз до примечания «Контекст проверки»

1 голос
/ 07 ноября 2011

Я думаю, что эта ссылка может вам помочь. Редактирование формы Zend и Zend_Validate_Db_NoRecordExists

Пользователь Db не должен существовать, но для редактирования можно указать атрибут исключения в проверке.

...