Yii, Модуль SRBAC часть 2. Пишем регистрацию.
После того как мы подключили и настроили модуль srbac нам необходимо сделать регистрацию пользователей на нашем сайте. Этим сейчас и займемся.
Оговорюсь сразу, что для выполнения этого урока требуется yii версии 1.1.1 и дополнение email.
Почему взята именно эта, а не стабильная версия 1.1.0, потому что в новой версии появился очень интересный виджет «CActiveForm» позволяющий проводить валидацию форм на стороне клиента.
Кстати на счет этого виджета, если кто-то знает, как заставить его проводить валидацию по правилам, как например:
$model->validate('reg');
буду очень признателен.
Закончим это лирическое отступление и перейдем непосредственно к программированию.
Первым делам устанавливаем дополнение email. Как? На странице документации все подробно расписано и думаю, это затруднений не вызовет. Правда у данного модуля есть проблемка с отправлением сообщений на русском языке. Для ее устранения открываем “protected/extensions/email/Email.php” находим функцию mail() и заменяем mb_send_mail на mail. И все отлично работает.
У нас уже есть таблица User и конечно же модель User в папке “protected/models”. Вот как выглядит моя таблица User:
CREATE TABLE IF NOT EXISTS `User` ( `id` int(11) NOT NULL AUTO_INCREMENT, `email` varchar(100) NOT NULL, `username` varchar(100) NOT NULL, `password` varchar(32) NOT NULL, `createtime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, `activationKey` varchar(32) NOT NULL, `status` varchar(1) NOT NULL, PRIMARY KEY (`id`) )
На этом приготовления закончены, перейдем непосредственно к модулю регистрации.
Для этого создадим модуль “User” из консоли yiic и в DefaultController.php добавим функцию регистрации:
/*
* Регистрация
*
* @param
* @return
*/
public function actionRegistration() {
}
После добавим вспомогательные функции для ajax валидации данных и для отправки кода активации на почту.
protected function performAjaxValidation($model) {
if(isset($_POST['ajax']) && $_POST['ajax']==='user-form') {
echo CActiveForm::validate($model);
Yii::app()->end();
}
}
/*
* Отправление кода активации
*
* @param model $model
* @return bolean
*/
protected function activationKey($model) {
$email = Yii::app()->email;
$email->to = $model->email;
$email->subject = 'Код активации аккаунта для сайта '.Yii::app()->name;
$email->message = 'Код активации аккаунта: <a href="'.Yii::app()->homeUrl.'/user/default/activation/key/'.$model->activationKey.'">'.$model->activationKey.'</a>';
$email->send();
}
Тут все предельно просто. В первой функции проверяем, откуда пришел запрос и если он ajax то проводим валидацию данных.
Во второй функции создаем экземпляр класса email, устанавливаем значения для необходимых полей и отправляем письмо.
После этого простые рутинные операции, как при создании любой формы. Добавим действие captcha:
function actions() {
return array('captcha'=>array(
'class' =>'CCaptchaAction',
'maxLength' => 6,
'minLength' => 3,
'foreColor' => 0x667e9a,
'testLimit' => 2,)
);
}
Для вывода каптчи в форме регистрации и установим минимальную длинну кода на картинке в «3» символа, максимальную в «6», колличество попыток ввода до смены кода «2», что бы пользователь при ошибочном вводе кода видел свою ошибку.
Теперь создадим форму регистрации, для этого в папке «protected.modules/User/views/default» создадим файл “registration.php” и добавим следующий код:
<?php
$this->breadcrumbs=array(
"Регистрация",
);
?>
<h1>Регистрация</h1>
<div class="form">
<?php $form = $this->beginWidget('CActiveForm', array(
'id'=>'user-form',
'enableAjaxValidation'=>true,
)); ?>
<p class="note">Поля со <span class="required">*</span> обязательны.</p>
<?php echo $form->errorSummary($model); ?>
<div class="row">
<?php echo $form->label($model, 'email', array('class' => 'required')); ?>
<?php echo $form->textField($model, 'email')?>
<?php echo $form->error($model,'email'); ?>
</div>
<div class="row">
<?php echo $form->label($model, 'username'); ?>
<?php echo $form->textField($model, 'username' )?>
<?php echo $form->error($model,'username'); ?>
</div>
<div class="row">
<?php echo $form->label($model, 'password'); ?>
<?php echo $form->passwordField($model, 'password') ?>
<?php echo $form->error($model,'password'); ?>
</div>
<div class="row">
<?php echo $form->label($model, 'password2'); ?>
<?php echo $form->passwordField($model, 'password2') ?>
<?php echo $form->error($model,'password2'); ?>
</div>
<div class="row">
<?php $this->widget('CCaptcha', array('buttonLabel' => '<br>[новый код]')); ?>
<?php echo $form->label($model, 'captcha'); ?>
<?=CHtml::activeTextField($model,'captcha'); ?>
</div>
<div class="row submit">
<?=CHtml::submitButton('Зарегистрироваться', array('id' => "submit")); ?>
</div>
<?php $this->endWidget(); ?>
</div><!-- form -->
Перейдем к доработке модели User. Добавим два параметра:
public $captcha; public $password2;
Установим имена для аттрибутов:
public function attributeLabels() {
return array(
'email' => 'E-mail адресс:',
'username' => 'Имя пользователя:',
'password' => 'Пароль:',
'password2' => 'Пароль еще раз:',
'captcha' => 'Введите код с картинки:',
);
}
И опишем правила валидации для полей:
/*
* Правила валидации
*
* @param
* @return
*/
public function rules() {
return array(
array('email, username, password, password2, captcha', 'required', 'on'=>'reg'),
array('password2', 'compare', 'compareAttribute' => 'password', 'on'=>'reg'),
array('captcha', 'captcha', 'allowEmpty' => !extension_loaded('gd'), 'on'=>'reg'),
array('email, username', 'required', ),
array('email', 'match', 'pattern' => '/^([a-z0-9_\.-]+)@([a-z0-9_\.-]+)\.([a-z\.]{2,6})$/', 'message' => 'Не верный формат e-mail адреса.'),
array('username', 'match', 'pattern' => '/^[A-Za-z0-9_-А-Яа-я\s,]+$/u','message' => 'Логин содержит недопустимые символы.'),
array('username, email', 'length', 'max' => '100', 'min' => '3',),
array('password, password2', 'length', 'max' => '40', 'min' => '5',),
);
}
Расписывать правила валидации не буду, про это и так много всего написано.
Теперь создадим представление для сообщения об успешной регистрации. Добавим в «protected.modules/User/views/default» файл «registratoinOk.php» со следующим содержимым:
<?php
$this->breadcrumbs=array(
"Регистрация",
);
?>
<h1>Регистрация</h1>
<div id="content">
<h1>Пользователь успешно добавлен!</h1>
</div>
Ну и наконец перейдем непосредственно к коду нашей регистрации:
/*
* Регистрация
*
* @param
* @return
*/
public function actionRegistration() {
if (Yii::app()->user->isGuest) {
$user = new User;
/*
* Ajax валидация
*/
$this->performAjaxValidation($user);
if(empty($_POST['User'])) {
/*
* Если форма не отправленна, то выводим форму
*/
$this->render('registration', array('model' => $user));
} else {
/*
* Форма получена
*/
$user->attributes = $_POST['User'];
/*
* Валидация данных
*/
if($user->validate('reg')) {
/*
* Если проверка пройдена, проверяем на уникальность имя
* пользователя и e-mail
*/
if($user->model()->count("email = :email",
array(':email' => $user->email))) {
$user->addError('email', 'E-mail уже занят');
$this->render("registration", array('model' => $user));
} else if($user->model()->count("username = :username",
array(':username' => $user->username))) {
$user->addError('username', 'Имя пользователя уже занято');
$this->render("registration", array('model' => $user));
} else {
/*
* Если проверки пройдены шифруем пароль, генерируем код
* активации аккаунта, а также устанавливаем время регистрации
* и роль по умолчанию для пользователя
*/
$user->password = md5(md5($user->password));
$user->activationKey = substr(md5(uniqid(rand(), true)), 0, rand(10, 15));
$user->status = '0';
/*
* Проверяем если добавление пользователя прошло успешно
* устанавливаем ему права.
*/
if($user->save()) {
$role = new AuthAssignment();
$role->itemname = 'User';
$role->userid = $user->id;
if($role->save()) {
/*
* Если роль успешно добавилась, выводим сообщение
* об успешной регистрации и отправляем код активации аккаунта
*/
$this->render("registrationOk");
$this->activationKey($user);
} else {
throw new CHttpException(403, 'Ошибка добавления в базу данных.');
}
} else {
throw new CHttpException(403, 'Ошибка добавления в базу данных.');
}
}
} else {
/*
* Не прошел валидацию
*/
$this->render('registration', array('model' => $user));
}
}
} else {
/*
* Если пользователь залогинен редиректим обратно
*/
$this->redirect(Yii::app()->user->returnUrl);
}
}
Я думаю комментариев в коде достаточно, что бы просто его понять. Если возникнут вопросы пишите в комментариях.
В следующем уроке мы будем делать активацию аккаунта.
- Yii модуль srbac, Часть 1
- Активация аккаунта Yii
- Добавляем запись в твиттер с помощью PHP
- Регер аккаунтов 100zakladok.ru
- Пишем спамер Wordpress блогов

23 коммент.
Здорово. Уже давно ждал продолжения…
Пока один маленький вопрос:
А чем не устроил родной валидатор email?
Reply
оооо и правда)) Даже не знаю, что ответить) Заработался наверно…
Reply
Огромное человеческое спасбо!
Reply
Вы знаете редко сейчас кто пишет по данной тематике, очень приятно читать, я бы советовала картинок добавить еще!
Reply
Да, вот на счет картинок тоже думал)
Reply
Прочесть было очень интересно, а потом каша в голове.
не чего не понял как это работает.
Reply
а что именно не понятно?
Reply
Умиляет:
создаешь тему «Пишем спамер Wordpress блогов», а потом отвечаешь на спам
Reply
Ирония судьбы, спамеры в основном спамят пост про wordpress спамер
Reply
А как всю эту регистрацию запустить на сайте? по какой ссылке? и надо ли для модуля User прописывать что либо в config/main.php?
Reply
запустить можно по site,ru/user/default/registration а в конфиге надо просто добавить ‘user’ к массиву modules
‘modules’ => array(
‘user’,
),
Reply
Для проверки на уникальность можно использовать валидатор «unique»
«как заставить его проводить валидацию по правилам» – использовать сценарии
в правилах :
array(‘pwd’,'required’,'on’=>’registration’),
в контроллере
$model->scenario=’registration’;
Reply
если в #63 прошло сохранение в базу, а в #68 вылетел эксепшн, то получаем пользователя без выставленных прав
Reply
да) чет не подумал
Reply
Сделал все как описано в статье, но при попытке регистрации вываливается ошибка :
YiiBase::include(AuthAssignment.php) [function.YiiBase-include]: failed to open stream: No such file or directory
Матюкается видимо на этот кусок кода :
…
$role = new AuthAssignment();
…
Сохранение в базу проходит нормально.
Как решить данную траблу?
Спасибо.
Reply
Создать таблицу AuthAssignment в базе и создать модель AuthAssignment.
Для этого идем в директорию framework/web/auth/, там хранится схема нужных нам таблиц «schema.sql«. Просто копируем все содержимое в phpmyadmin и выполняем запрос. У нас в базе появились 3 новых таблицы:
цитата из первой статьи
Reply
при создании экземпляра модели указываем сценарий и проверка идет по данному сценарию
$user = new User(‘reg’);
Reply
Ругается, в логе пишет:
Не удалось присвоить небезопасный атрибут «captcha»
Функция:
01 protected function performAjaxValidation($model) {
02 if(isset($_POST['ajax']) && $_POST['ajax']===’user-form’) {
03 echo CActiveForm::validate($model);
04 Yii::app()->end();
05 }
06 }
Строка 3.
Help me!
Reply
yii какой версии?
если 1.0.*
то нужно добавить
public function safeAttributes()
{
return array(
parent::safeAttributes(),
‘reg’ => ‘captcah и все остальные через запятую’
);
}
Reply
Спасибо!
Я сделал в модели:
array(‘captcha’, ’safe’),
Но, правильно ли теоретически? Привычка, подвергать сомнениям ВСЁ, что вводит пользователь на своё усмотрение.
Reply
ну можно проверить данные, хотя они же ни куда не сохраняются и не выводятся, так что не особо важно
Reply
Спасибо за статью, но у вас ошибочка имеется.
Вместо:
$email->message = ‘Код активации аккаунта: homeUrl.’/user/default/activation/key/’.$model->activationKey.’»>’.$model->activationKey.’‘;
нужно:
$email->message = ‘Код активации аккаунта: request->hostInfo.’user/default/activation/key/’.$model->activationKey.’»>’.$model->activationKey.’‘;
Reply
Обрезало немного
Вот это нужно писать:
Yii::app()->request->hostInfo
а не
Yii::app()->homeUrl
Reply