current_user = $current_user;
parent :: __construct($field);
}
function check($value)
{
$user = new User();
$records = $user->findAllRecords(new lmbSQLFieldCriteria($this->field_name, $value));
if($records->count() && ($this->current_user->isNew() || $this->_sameFieldUserRecordExists($records)))
$this->error('User with the same value of {Field} already exists');
}
function _sameFieldUserRecordExists($records)
{
foreach($records as $record)
{
if($record->get('id') != $this->current_user->getId())
return true;
}
return false;
}
}
?>
Класс UserUniqueFieldRule получает в конструкторе название поля, которое должно быть уникальным, и ссылку на текущего пользователя. Текущий пользователь понадобится нам при редактировании.
Класс **lmbSingleFieldRule** является базовым для правил валидации одного поля. Файл класса можно найти по пути limb/validation/src/rule/lmbSingleFieldRule.class.php Дочерние классы должны перекрывать метод **check($value)**, где $value - значение поля, которое необходимо проверить. Следует отметить, что check($value) не вызывается, если $value не содержит значимого значения. Поэтому совместно с этим правилом (его дочерними) рекомендуется использовать также правило **lmbRequiredFieldRule**. Об этом ты также упомянем чуть ниже при описании кода класса User.
При помощи [[limb3:ru:packages:active_record:find|find-метода класса lmbActiveRecord]] делается запрос к базе данных. В качестве второго параметра вместо $params можно передавать объект критерии, которая будет накладываться на выборку. Критерия - это объектная форма условия. В нашем случае использовался класс **lmbSQLFieldCriteria**, который принимает в конструкторе название поля и значение (по-умолчанию для этой пары формируется условие равенства). Использование критериев позволяет не думать о экранировании данных в SQL-запросах. Вы можете подробнее ознакомиться с классами [[limb3:ru:packages:dbal:criteria|Criteria]], однако это необязательно для понимания данного примера.
Метод lmbSingleFieldRule :: **error($error_string, $values = array())** добавляет ошибку в список ошибок валидации. Выражения вида {Field} будут заменены в процессе работы на реальные имена полей формы, с которой производится создание/редактирование пользователя.
==== Код класса User ====
Теперь можно написать код класса User.
Файл shop/src/model/User.class.php:
'ASC');
protected $password;
protected function _createValidator()
{
$validator = new lmbValidator();
$validator->addRequiredRule('login');
$validator->addRequiredRule('email');
$validator->addRequiredRule('name');
lmb_require('src/validation/UserUniqueFieldRule.class.php');
$validator->addRule(new UserUniqueFieldRule('login', $this));
$validator->addRule(new UserUniqueFieldRule('email', $this));
lmb_require('limb/validation/src/rule/lmbEmailRule.class.php');
$validator->addRule(new lmbEmailRule('email'));
return $validator;
}
protected function _onBeforeSave()
{
$this->_generatePassword();
}
protected function _generatePassword()
{
if($this->password)
$this->setHashedPassword(self :: cryptPassword($this->password));
}
static function cryptPassword($password)
{
return md5($password);
}
}
?>
Создаваемый в методе _createValidator() валидатор проверяет, что поля email и login должны быть заполнены и иметь уникальные значения. Последнее обеспечивается за счет использования правила UserUniqueFieldRule. Правило lmbEmailRule удостоверяется, что введенное в поле значение является электронным адресом.
Обратите внимание на метод **_onBeforeSave()**. Это так называемый метод расширения класса lmbActiveRecord, который дочерние классы могут использовать чтобы выполнять необходимые действия, например, перед сохранением новой записи, перед обновлением существующей, после сохранения и т.д. Список методов расширения класса lmbActiveRecord есть в разделе [[limb3:ru:packages:active_record:enhancement|"Расширение поведения базового класса lmbActiveRecord"]].
В нашем случае мы использовали этот метод, чтобы шифровать поле **password** и формировать значение поля **hashed_password**. Таким образом мы будем хранить только хешированный пароль, а обновление хешированного пароля будет происходить только, если в поле password есть новое значение.
===== Создание шаблонов и контроллера для управления пользователями =====
Надеемся, что это часть не составит для Вас никакого труда. Новые для вас моменты должны быть в реализации действий по созданию нового пользователя и смене пароля в контроллере AdminUserController. Там мы будем использовать дополнительный валидатор для проверки полей с паролями. Получится, что в итоге данные с одной формы будут валидироваться дважды - один раз в контроллере, другой раз в ActiveRecord-е.
==== Шаблоны ====
Файл shop/template/admin_user/create.html:
Файл shop/template/admin_user/edit.html:
Файл shop/template/admin_user/form_fields.html:
Файл shop/templates/admin_user/display.html:
Create user
Name
Login
E-mail
Actions
{$name}
{$login}
{$email}
Change password
Edit
Delete
==== Контроллер AdminUserController ====
При реализации контроллера AdminUserController мы также создадим общий метод _performCreateOrEdit(), как и в AdminProductController, который будет отвечать за создание и редактирование учетных записей пользователей.
Дополнительно вы введем проверку при создании пользователя, что значения полей password и repeat_password должны совпадать. Так мы покажем как можно валидировать данные, пришедшие с форм, прямо в контроллере.
Файл shop/src/controller/AdminUserController.class.php:
_performCreateOrEdit();
}
function doEdit()
{
$this->_performCreateOrEdit();
}
protected function _performCreateOrEdit()
{
if(!$id = $this->request->getInteger('id'))
$id = null;
$item = new User($id);
$this->useForm('user_form');
$this->setFormDatasource($item);
if($this->request->hasPost())
{
$item->import($this->request);
if($this->request->get('create'))
$this->_validatePasswordField();
if($item->trySave($this->error_list))
$this->redirect();
}
}
function doDelete()
{
$item = new User($this->request->getInteger('id'));
$item->destroy();
$this->redirect();
}
function _validatePasswordField()
{
$this->validator->addRequiredRule('password');
$this->validator->addRequiredRule('repeat_password');
lmb_require('limb/validation/src/rule/lmbMatchRule.class.php');
$this->validator->addRule(new lmbMatchRule('password', 'repeat_password'));
$this->validator->validate($this->request);
}
}
?>
Рассмотрим метод **_validatePasswordField()**. Класс lmbController по-умолчанию содержит объект валидатора **$validator**, которому передали список ошибок $error_list. В методе мы добавили в этот валидатор три правила:
* lmbRequiredRule для поля repeat_password,
* lmbRequiredRule для поля password и
* lmbMatchRule для полей password и repeat_password. lmbMatchRule удостоверяется, что значения двух полей совпадают.
Метод lmbValidator :: **validate($datasource)** проверяет переданный контейнер данных $datasource при помощи ранее добавленных в него правил. В нашем случае мы отдали на проверку объект Запроса $request.
Теперь можете попробовать создать уникальных пользователей, пользователей с дублирующимися логинами и т.д.
==== Смена пароля пользователей ====
Добавим также действие по смене пароля, скажем **change_password**. Текущий зарегистированный администратор сможет легко менять пароли пользователей. Для этого нам необходимо будет добавить новый метод **doChangePassword()** в **AdminUserController** и новый шаблон **change_password.html**:
Файл shop/template/admin_user/change_password.html:
Изменения в файле shop/src/controller/AdminUserController.html:
class AdminUserController extends lmbController
{
[...]
function doChangePassword()
{
if(!$this->request->hasPost())
return;
$this->useForm('user_form');
$this->setFormDatasource($this->request);
$this->_validatePasswordField();
if(!$this->error_list->isValid())
return;
$user = new User($this->request->getInteger('id'));
$user->setPassword($this->request->get('password'));
if($user->trySave($this->error_list))
$this->redirect();
}
[...]
}
Здесь мы также использовали метод _validatePasswordField() для проверки полей для ввода паролей.
===== Далее =====
Мы сделали модуль по управлению пользователей. Мы рекомендуем вам при помощи этой новой функциональности добавить себе пользователя с установленных флагом "Is Admin" и приступить к следующему шагу: [[step4-2|"Шаг4.2 Аутентификация пользователей"]].