Думаю, всем известен стандартный механизм создания и использования объектов Validation
в Kohana
:
// подготавливаем данные - извлекаем только нужные поля $data = Arr::extract($this->request->post(), array('foo', 'bar')); // создаем валидатор $valid = Validation::factory($this->request->post()); // добавляем правила $valid->rules('foo', array(...))->rules('bar', array(...)); // собственно валидируем if ($valid->check()) {...} |
Как часто бывает, что механизм проверки в разных частях сайта одинаков (или по большей части совпадает)? И тут в голову приходит мысль, что подготовительную часть можно спрятать в сам валидатор!
abstract class Validation_Template extends Validation { public static function factory(array $array) { return new static($array); } public function __construct(array $array) { if ( $fields = $this->_fields() ) { $array = Arr::extract($array, $fields); } parent::__construct($array); // добавляем метки $this->labels($this->_labels()); // добавляем правила foreach($this->_rules() as $field => $rules) { $this->rules($field, $rules); } } /** * Позволяет фильтровать поля в массиве данных, оставляя только нужные * @return array */ protected function _fields() { return array(); } /** * Метод по аналогии с ORM-методом rules * @return array */ protected function _rules() { return array(); } /** * Задаем метки для проверяемых полей * @return array */ protected function _labels() { return array(); } } class Validation_Foo extends Validation_Template { protected function _fields() { return array('foo', 'bar'); } protected function _rules() { return array( 'foo' => array( array('not_empty'), array('max_length', array(':value', 32)), ), 'bar' => array( array('not_empty'), ), ); } protected function _labels() { return array( 'foo' => 'Foo field', 'bar' => 'Bar field', ); } } // в контроллере $valid = Validation_Foo::factory($this->request->post()); if ($valid->check()) {...} |
Итого, мы имеем возможность разгрузить контроллеры от необязательной логики, вдобавок облегчив себе повторное использование кода. Обратите внимание, что метки и правила устанавливаются не напрямую в свойства $_rules
и $_labels
, а через вызовы методов. Это сделано для того, чтобы можно было создать иерархию валидаторов, наследуя от предков созданные ими метки и правила:
class Validation_Baz extends Validation_Foo { public function _fields() { // добавляем поле baz к исходному списку return array_merge(array('baz'), parent::_fields()); } } |
Конечно, это не самая востребованная фича, но знать о такой возможности стоит.
Как вариант, можно не создавать
Validation_Template
, а расширить классValidation
. Но в любом случае, придется при создании шаблонных валидаторов указывать их класс (Validation_Foo::factory($data)
илиnew Validation_Foo($data)
)
Добрый день.
Скажи пожалуйста, при использовании этих идей в Gleez, какую ссылку мы должны оставлять в исходниках ссылаясь на эту статью или тебя конкретно?
Только наверное не
if ( ! empty($this->_fields() )
а
if ($this->_fields())
Ничего не надо я пишу за идею
Кстати очень странное поведение..
Дело в том, что во время выполнения
Validation_Template::__construct
метод_fields()
возвращает 0. И если посмотреть на это дело со стороны класса потомкаValidation_Foo
то этот метод всё равно возвращает 0. Хоть блин в каждом классе заново описывай всё. Пробовал использовать не метод, а поле. В классеValidation_Foo
объявляюprotected $_validation
, в этом же классе в конструкторе наполняю поле нужными значениями и выполняюparent::__construct($array)
передавая выполнение классуValidation_Template
, в родительском классе естественно поле так же объявлено, в конструкторе, по аналогии с твоим примером выше распаковываю это дело в$array
и всё равно, какой бы я способ не использовал$_validation
или_fields()
в конструкторе fields не наполняются нужными значениями. Магия?У тебя вообще это дело работало?
Работало.. в первых версиях )) В последнюю я внес кое-что, что лень было проверять поздно ночью. Подправил код Validation_Template.
Обрати внимание на метод Validation_Template::factory() — он переопределяет дефолтную фабрику и использует static (php 5.3+). Другой вариант — дергать контроллер вместо фабрики (new Validation_Foo($data)).
Да!
сильно упростило жизнь. Спасибо!
Сюда бы еще добавить _filters()
Вообще не понятно, вроде были до версии 3.1, зачем убрали непонятно.
Или как это красиво сделать? Я использовал array_map на весь $_POST
Убрали с формулировкой «фильтрация данных не имеет ничего общего с валидацией». В принципе, я с этим согласен. Если говорить про ORM, то там фильтрация предполагается на уровне присвоения значения полю (метод set(), насколько я помню).
В нашем случае вполне можно добавить фильтры в шаблоны валидации, поскольку это уже не столько базовый валидатор, сколько сервисная обертка вокруг него, тут уже доп. функционал уместен.
debug-toolbar сейчас вышел в топ most forked today на гитхабе — https://github.com/languages/PHP