Совместное использование Zend_Validate и помощника действий Zend_Controller_Action_Helper

Как часто вам приходится делать валидацию данных в своем приложении? Если у вас достаточно много форм с отправляемыми данными, и каждый раз вы проверяете их на корректность, то эта статься для вас. Она расскажет, о том как написать свой помощник действий Zend_Controller_Action_Helper, о том как написать свой валидатор и том, как же использовать их вместе так, чтоб в любой части приложения вы лишь вызвали написаный хелпер, передав ему ассоциативный массив с названием поля и валидатора, который к этому полю надо применить. Вот так:
$valid_data = array('name' => array('Alpha' => $profile_data['name']),
                    'login' => array('Alnum' => $profile_data['surname'])
                    );
if ($this->_helper->validate->isValid($valid_data, $errors) === true)
{

// делаем что либо

}

Если у вас лишь пара полей, которые надо проверить, то конечно можно обойтись и стандартным методом, создав объект Zend_Validate. А если у вас их 10, или даже 20? Ведь гораздо удобней оформить все одним массивом, и скормить его хелперу ;)
И так, приступим.

Index.php

Убедитесь, что в index.php для функции set_include_path() вы указали папку с Zend Framework. У меня это /lib Так же эту папку мы будем использовать, чтоб складывать туда написанные нами валидаторы и хелперы.
Не забываем и про помощников действий. Тут же, в index.php пишем:

Zend_Controller_Action_HelperBroker::addPath(LIBPATH.'/My/Helper/Action', 'My_Helper_Action');

Подразумеваается что, в LIBPATH у нас путь к той самой папке /lib. Все в соответствии с соглашением по именованию файлов и директорий.

Помощник действий

Ну вот, теперь приступим к написанию помощника дейтсвий. По примеру приведенному в самом начале статьи, вам уже наверное стало ясно, как мы будем его использовать. В контроллере (конечно же можно и в моделе, но мы то помним о принципе "тонкий контроллер, толстая модель") мы будем вызывать метод isValid нашего помощника и передавать ему ассоциативный массив, с нашими проверяемыми данными и названиями валидоторов, которых к ним надо применить. Валидаторы можно указывать, как и зендовские, так и наши - самописные. Наш помощник будет содержать 2 метода: getValidator и isValid. Последний будет вызывать первый, для получения объекта валидатора. Расположение: /lib/My/Helper/Action/Validate.php

<?php

require_once 'Zend/Controller/Action/Helper/Abstract.php';
require_once 'Zend/Validate.php';

class My_Helper_Action_Validate extends Zend_Controller_Action_Helper_Abstract
{

    protected $validator;
      
    public function direct()
    {
       
    }
   
    /**
     * Возвращает объект валидатора
     *
     * @param unknown_type $validator_name имя требуемого валидатора
     * @return unknown
     */
    public function getValidator($validator_name){
        if (!preg_match('/My/', $validator_name)){
            require_once('Zend/Validate/'.$validator_name.'.php');
            $validator = 'Zend_Validate_'.$validator_name;
        }
        else {
            require_once('My/Validate/'.$validator_name.'.php');
            $validator = 'My_Validate_'.$validator_name;
        }  
        return new $validator();
    }
   
    /**
     * Проверяет массив данных в соотвествии с заданными валидаторами
     *
     * @param array $fields массив с данными для проверки и именами валидаторов
     * array('some_field_name' => array('validator_name' => $value));
     * @param array $errors массив с ошибками
     * @return bool в случае успешной валидации вернет true
     */
    public function isValid($fields, &$errors){
        $count_error = count($errors);
       
        // извлекаем из массива поле и валидатор, которым его надо обработать
        foreach ($fields as $values){
            foreach ($values as $validator_name => $value) {
                if (!empty($value)){
                    $validator = $this->getValidator($validator_name);
                    if (!$validator->isValid($value)) {
                        array_push($errors, 'Ошибка валидации: '.array_shift($validator->getMessages()));
                    }   
                }
            }
        }
        // число ошибок на входе равно числу ошибок после валидации?
        if (count($errors) == $count_error) {return true;}
        else {  return false;}
    }

}

Как вы наверное уже заметили, вторым аргументом методу isValid мы передали массив $errors. Туда занесем все сообщения об ошибках валидации, которые произошли. Я проверяю число записей об ошибках в начале метода и в конце. Если их колличество одинаково - все данные прошли валидацию. У меня этот массив так же используется в методе контроллера для прочих сообщениях об ошибках, поэтому при передачи его хелперу, он уже возможно не пустой. Вы можете поступать как вам угодно, но если методу передаете пустой массив, то конечно же его следует определить перед вызовом хeлпера:

$errors = array();

И так, мы уже можем использовать хелпер в контроллере, но только если будем вызывать валидаторы зенда. Вобщем-то мы можем использовать и свои валидаторы, но у нас их пока нет. Давайте и займемся их написанием.

Написание собственных валидаторов

В качестве примера напишем валидатор для проверки логина.  Наш логин может быть длиной от 3 до 36 символов, и содержать только буквы, цифры, а так же "-" и "_"
Валидатор будет распологаться здесь: /lib/My/Validate/Mylogin.php

<?php
require_once 'Zend/Validate/Interface.php';
require_once 'Zend/Validate/StringLength.php';

/**
 * Допустим логин длинной от 3 до 36 символов
 * и логин в котором есть только цифры, буквы и "-", "_"
 *
 */
class My_Validate_Mylogin implements Zend_Validate_Interface
{
    protected $_messages;
   
    public function isValid($value)
    {
        $this->_messages = array();
        $validatorStringLength = new Zend_Validate_StringLength(3, 36);
        $pattern = "/^[-_a-zA-Z0-9]+$/";

        if ($validatorStringLength->isValid($value))
        {
            if(preg_match($pattern, $value)) {return true;}
            else {$this->_messages[] = "неккоректное значение логина"; return false;}
        } else    
            $this->_messages[] = "длина логина не верна"; return false;
   
    }

    public function getMessages()
    {
        return $this->_messages;
    }
   
    public function getErrors(){
        return array();
    }
}

В документации вы найдете более полную информацию о том какие методы должны быть реализованы и как. Для проверки длины я привела пример использования Zend_Validate_StringLength. Всё остальное проверяется регулярным вырежением. Вы вольны делать это по свойму, используя например Zend_Validate_Alnum. Это лишь пример того, как может быть реализована идея более удобного использования валидаторов в контроллерах.


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

     $valid_data = array('name' => array('Alpha' => $profile_data['name']),
                                'surname' => array('Alpha' => $profile_data['surname']),
                                'fatname' => array('Alpha' => $profile_data['fatname']),
                                'birthday' => array('Mydate' => $profile_data['birthday']),
                                'phone1' => array('Myphone' => $profile_data['phone1']),
                                'pass' =>     array('Mypass' => $profile_data['pass']));

$this->_helper->validate->isValid($valid_data, $errors)
        if (count($errors) > 0) {
            // Ошибки на вывод
            $this->view->assign("errors", $errors);
        } else {
           // Работа с моделью
        }


Итог

Вот и всё. Теперь вы знаете, как подключать, писать и использовать помощники действий и валидаторы. Я не утверждаю, что это лучший путь для использования, это лишь учебный пример, и надеюсь он был для вас полезен.


Раздел: Веб-Разработка Рубрика: Zend Framework


Добавлена: 02-03-2009 | | Пользователем: olga | Просмотров: 2295


Оставить комментарий



        
        

Капча *

                 Captcha
                          

        

Комментарий будет опубликован после проверки модератором

Для подсветки синтаксиса исходный код следует обрамлять следующими тэгами
<pre><code class="синтаксис" >код</code></pre>
Подерживаются следующие: cpp php javascript sql html-xml css ini