Валидация формы средствами Yii
Рубрика: Работа с формами
27 Апр. 2009Эта статья устарела т.к. была написана для yii версии 1.0.х; Если вы используете более новую версию - у вас могут возникнуть ошибки из-за несовместимости. Обычно ответы на все вопросы работы на 1.1.х были описаны в комментариях ниже статьи.
Сегодня мы будем учиться делать форму с валидацией на Yii. Хочу сразу заметить что сам фреймворк даёт нам огромный функционал для валидации и создания наших веб форм.
Давайте разберем с вами как на Yii можно создать простую форму для регистрации (поле логин, пароль) и проверить данные с формы перед тем как добавить в таблицу.
---Для начала договоримся что у нас в базе должна быть табличка user с которой мы и будем работать:
CREATE TABLE `user` (
`id` int(11) NOT NULL auto_increment,
`login` varchar(250) NOT NULL,
`passwd` varchar(250) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=11 ;
Как видите она содержит в себе всего три поля: номер записи, логин, пароль.
Теперь нам надо создать модель Users.php:
class Users extends CActiveRecord
{
public $passwd2;
public static function model($className=__CLASS__)
{
return parent::model($className);
}
public function tableName()
{
return 'user';
}
public function rules()
{
return array(
);
}
public function attributeLabels()
{
return array(
'login' => 'Логин',
'passwd' => 'Пароль',
);
}
public function safeAttributes()
{
return array(
'login',
'passwd',
'passwd2',
);
}
} Тут у нас тоже ничего необычного:
- В tableName я указал что мы используем таблицу с именем «User»
- В attributeLabels указал синонимы для полей таблицы. Это удобно что б наша форма выглядела по человечески. Т.е. в форме теперь вместо «login» у нас будет «Логин» и т.п. Если непонятно зачем это надо и что оно делает – удалите и посмотрите какой вид приймет ваша форма.
- Также я переопределил метод «rules» который содержит в себе правила валидации. Пока что метод пустой т.к. правила валидации мы рассмотрим чуть дальше.
- safeAttributes– это метод который позваляет нам указать название полей таблицы которые мы допускаем для изменения через форму. Данный метод необходим для безопасности и не стоит некогда его упускать.
Теперь в принципе когда модель у нас есть – надо приступить к созданию формы и контроллера.
Заходим в protected/controllers и создаем там UserController.php:
class UserController extends CController
{
public function actionIndex()
{
$form = new Users();
if (!empty($_POST['Users']))
{
$form->attributes=$_POST['Users'];
if($form->validate()) {
// Валидация прошла успешно
// Добавляем данные в базу
$form->save();
}
}
$this->render('reg', array('form' => $form));
}
}
Для простоты и удобства я создал один экшинс который будет выводить на экран нам форму для регистрации, и если данные из формы были получены – тут же будет проверять их.
Хочу обратить ваше внимание на следующую конструкцию
$form->attributes=$_POST['Users'];
Данная запись выполняет так сказать массовое присваивание элементов форм экземпляру класса модели ($form). Т.е. простыми словами одна эта строчка совершает следующие действия:
foreach($_POST['Users'] as $name=>$value)
{
$form ->$name=$value;
}
Еще момент, метод validate проверяет удволитворяют ли данные $form условиям валидации. Если данные нарушают хоть одно из правил – форма не будет сохранена, а на экран будут показы ошибки.
Идем дальше, создаем форму в отображении. Для этого заходим в protected/views/user и создаем там файлик reg.php:
<?php echo CHtml::form(); ?>
<?php echo CHtml::errorSummary($form); ?><br>
<table border="0" width="400" cellpadding="10" cellspacing="10">
<tr>
<td width="150"><?php echo CHtml::activeLabel($form, 'login'); ?>
<td><?php echo CHtml::activeTextField($form, 'login') ?>
<tr>
<td><?php echo CHtml::activeLabel($form, 'passwd'); ?>
<td><?php echo CHtml::activePasswordField($form, 'passwd') ?>
<tr>
<td><?php echo CHtml::activeLabel($form, 'passwd2'); ?>
<td><?php echo CHtml::activePasswordField($form, 'passwd2') ?>
<tr>
<td>
<td><?php echo CHtml::submitButton('Войти'); ?>
<?php echo CHtml::endForm(); ?>
Как вы заметили вместо создания элементов на чистом Html-е мы используем класс помошника CHtml. Данная статья не включает в себя описание работы класса CHtml но в двух словах расскажу что к чему:
- activeTextField – создает текстовое поле (input type=text)
- activePasswordField – создает поле типа password (input type=password)
- submitButton – создаем субмит кнопочку
- errorSummary – место где будут выводиться ошибки валидации (если такие будут)
- form…endForm – начало и конец нашей формы
Вот в принципе у нас всё и готово (кроме правил валидации). Давайте теперь зайдем на страницу с нашей формой и посмотрим что получилось (user/index). Если вы заполните форму и нажмете «регистрация» – вы добавите нового пользователя в таблицу.
Теперь давайте придумаем правила (rules) для нашей формы по которым мы будем контролировать данные которые нам ввели:
- Поле логин, пароль и повтор пароля не должны быть пустыми
- Поле пароль должно совпадать с полем повторить пароль
- Поле логин и пароль должны быть больше трёх символов.
- Поле логин также должно быть не больше десяти символов.
Заходим в нашу модель protected/models/Users.php:
И в метод rules добавялем по порядку правила которые мы придумали выше.
array('login, passwd', 'required'),- в первом параметре мы перечисляем название полей формы, вторым параметром – способ валидации. В данном случае 'required' говорит о том что наши два поля не должны быть пустыми
array('passwd', 'compare', 'compareAttribute'=>'passwd2'),
таким образом мы указываем что поле passwd должно быть равно с passwd2.array('login,passwd', 'length', 'min' => 3),
array('login ', 'length', 'max' => 10),
Теперь если сгруппировать это всё вместе то метод rules должен выглядеть следующим образом:
public function rules()
{
return array(
array('login, passwd, passwd2', 'required'),
array('passwd', 'compare', 'compareAttribute'=>'passwd2'),
array('login, passwd', 'length', 'min' => 3),
array('login ', 'length', 'max' => 10),
);
}
Больше нам с вами некакого кода писать не надо. Теперь при нажатии кнопки «регистрации» в нашем контроллере отработает строчка:
if ($form->validate) {
Которая в случае корректно введенных данных – сохранит их в базу, а в случае если данные не будут удволитворять правилам – выведет ошибки на экран.
Надеюсь данная статья оказалась вам полезной.
Пользуйтесь Yii и будет вам счастье =)
Если хотите опубликовать этот материал у себя - пожалуйста, разместите ссылку на страницу откуда вы его взяли.
- Очень часто мне приходится заставлять работать проекты с практически идентичной структурой базы данных. Когда хостинг накладывает на меня ограничение что ... "Используем префиксы для таблиц"
- Эта статья устарела т.к. была написана для yii версии 1.0.х; Если вы используете более новую версию - у вас могут ... "Урок2 : Первичная настройка"
- Это руководство предназначено для более-менее продвинутых пользователей. Если вы только что начали работу с Yii Framework-ом, вам стоит вернутся ... "Многоязычность субдоменов и URL-правила"

[adm] zolter
Было сказано: Понедельник, 27 Апрель 2009
Сори что мало писал на этой неделе, работа все дела.
На днях постараюсь написать еще пару статей по основам программирования на Yii.

romanoza
Было сказано: Вторник, 28 Апрель 2009
не знаешь, как проапдейтить реляционную AR?
т.е. поле в проджойненой таблице

[guest] Ric
Было сказано: Среда, 29 Апрель 2009
Спасибо за создание блога!!! Все очень полезно!!! Пишите еще!!!

[guest] Гость
Было сказано: Четверг, 28 Май 2009
Расскажите, как делать ajax-валидацию форм в Yii, без перезагрузки

[guest] Ponf
Было сказано: Пятница, 12 Июнь 2009
Снова косяк)
Fatal error: Call to a member function getErrors() on a non-object in Z:\home\blog.ru\framework\web\helpers\CHtml.php on line 1375

[adm] zolter
Было сказано: Пятница, 12 Июнь 2009
Сенк :)
Замени:
$this->render('reg');на:
$this->render('reg', array('form' => $form));это в контроллере.

[guest] Ponf
Было сказано: Пятница, 12 Июнь 2009
А раз мы создали новые модель-контроллер-вид для регистрации, то она будет доступна только по user/index?
Можно её как-нибудь её вставить в уже существующий виджет?

[guest] Гость
Было сказано: Суббота, 13 Июнь 2009
Ну так как контроллер называеться user а экшинс index - тогда да. будет доступна только по user/index. вы можете сами в конфиге прописать другой маршрут если это надо.

[guest] hex
Было сказано: Воскресенье, 28 Июнь 2009
Please write in english...it's a nice article ..but it's a pain reading it...when google translates it

[adm] zolter
Было сказано: Вторник, 30 Июнь 2009
К сожалению, я не настолько хорошо владею английским что бы писать статьи на нем. :)

[guest] zolter
Было сказано: Среда, 24 Февраль 2010
Перед сохранением в базу сделайте к примеру:
$model->passwd = md5($model->passwd);

[guest] Гость
Было сказано: Понедельник, 15 Март 2010
Было бы интересно почитать о том, как перевести сообщения об ошибках на русский язык.

Kros
Было сказано: Четверг, 18 Март 2010
"Гость", http://dbhelp.ru/multilingual-blog/page/
мне вроде как хватило строчки 'language' => 'ru' в конфиге, framework/messages/ru/yii.php - тут фразы можно при желании перевести на свой офигенский сленг)
также можно поиском(желательно поддерживающим utf8) найти файлы с нужными фразами и попереводить их, если вдруг какие не перевелись или неизвестен норм способ.
за статью сенк, оффициальные документация и описание API просто нервно курят в сторонке, а тут так просто, и почему так..)

[guest] zolter
Было сказано: Четверг, 18 Март 2010
>> Было бы интересно почитать о том, как перевести сообщения об ошибках на русский язык.
Какие именно сообщения об ошибках? При обработке полей формы?

kros
Было сказано: Четверг, 08 Апрель 2010
zolter, грац с восстановлением блога :)))
вопрос по формам), как вставить текст в текстарею из модели? через ActiveForm.
вроде должно быть так просто, а не получается, к скриптам и обычному html не хочется уходить.
всё отлично приходит из контроллера, в инпуты всё вставляется через аттрибут value, а куда вставлять в текстарею, где находится место между тегами - непонятно.
Или как обычно вставляется в админке текст?

[adm] zolter
Было сказано: Пятница, 09 Апрель 2010
Если текстарэй делаете как CHtml элемент - то оно само вставит значение, а вот если делаете ручками как обычный html то вот так:
<textarea name="tratar"><?php echo $form->tvoe_pole; ?></textarea>

[guest] kros
Было сказано: Суббота, 10 Апрель 2010
спасибо))) всё заработало на CHtml))) просто тогда отправлял другой пустой экземляр модели, не думал что можно настолько проще))

[guest] Jay
Было сказано: Пятница, 16 Июль 2010
Хай пипл. Валидатор URL Yii пропускает <script> и `. Как быть? Возвращаться к своим фильтрам? Или можно, что-то исправить или добавить?

[guest] zolter
Было сказано: Воскресенье, 18 Июль 2010
что значит пропускает? покажите пример правила. Ограничьте на "<" и ">". вам же yii позволяет использовать регулярки как только вздумается

[guest] Гость
Было сказано: Четверг, 25 Ноябрь 2010
Спасибо за статью.
Ты сделал пример для контролера User.
В этом контролере как правило много других действий(acton)
Будут ли конфликты из-за safeAttributes & rules?
Или под каждую форму писать свои MVC?

[guest] Glok
Было сказано: Понедельник, 30 Май 2011
До сих пор актуально)) это лучше чем изучать создание блога на сайте с yii, не стоило там в самом начале показывать, что можно генерировать через консоль всё) ручками всё надо для начала)

[guest] Гость
Было сказано: Суббота, 27 Август 2011
тоже в первый раз сталкнулся, долго не мог понять в чем проблема, свойство через ниж слеш _attributes

[guest] Гость
Было сказано: Среда, 30 Ноябрь 2011
Собрал пример. Пишет :
"Property "UserController.breadcrumbs" is not defined"
Но бредкрамбс вроде должно в виде определяться?
Зашел в тупик... Поможете?
Там в начале статьи написано, что на Yii 1.8 может и не работать. А в чем отличия?

[guest] Гость
Было сказано: Воскресенье, 29 Январь 2012
Я новичок, ногами не пинайте. Вопросик, откуда берется имя массива "Users"
$form->attributes=$_POST['Users'];

[guest] zolter
Было сказано: Воскресенье, 29 Январь 2012
В отображении у нас используется переменная $form, которая моделью Users. С помощью неё мы создаем там поля, и они автоматически имеют имена Users[имя поля]. Поэтому когда нажимают отправить форму - в контроллер приходит массив Users

[guest] Гость
Было сказано: Понедельник, 30 Январь 2012
Спасибо! Немного разложилось по полочкам. Еще вопросик, вот не могу понять как модель взаимодействует с отображением. Вот в модели имеются методы attributeLabels()и safeAttributes()как они взаимодействуют с отображением?
Если не сложно ответьте пожалуйста...


