Предисловие
Доброе время суток хабравчане.
Для начала представлюсь. Меня зовут Роман, и я занимаюсь разработкой сайтов (в основном на php-фреймворке «yii», но проскакивают и другие php\python фреймворки\цмс\велосипеды\быдлокоды). В своих проектах на yii всеы нам часто приходится реализовывать тривиальные функции регистрации, авторизации и тд. Плюс ко всему прибавьте к этому ещё и распределние прав доступа для различных пользователей. Готов поспорить, что у каждого толкового разработчика есть хотя бы одна заготовка реализации этого функционали, либо он использует сторонее расширение. Вот и я каждый раз использовал одну и туже реализацию, от пректа к проекту допиливал её, интегрировал с другими частями системы. Но недавно я всё же решил порыть в сторону готовых решений, которые удовлетворяли бы мои потребности и таковые нашлись довольно быстро. 2 самых популярных расширения для yii из оффициального репозитория – «yii-user» и «rights».
Интеграция
Оба расширения оформлены в виде модулей. Так что могут быть легко интегрированны в уже существующий проект (если в вашем проекте уже есть модули «user» и «rights» сделайте бекапы), но я для чистоты буду их соединять в новом приложении. Для начала его нужно создать, как это делать отлично описано в документации. Скачиваеим дополнения и распаковываем в папку /protected/modules (её может не быть, создайте вручную). Теперь в нашем проекте появились 2 новых модуля – «user» и «rights». Включим их в конфиге (/protected/config/main.php).
'import'=>array( #... 'application.modules.user.*', 'application.modules.user.models.*', 'application.modules.user.components.*', 'application.modules.rights.*', 'application.modules.rights.models.*', 'application.modules.rights.components.*', #... ), 'modules'=>array( #... 'user' => array( // названия таблиц взяты по умолчанию, их можно изменить 'tableUsers' => 'tbl_users', 'tableProfiles' => 'tbl_profiles', 'tableProfileFields' => 'tbl_profiles_fields', ), 'rights', #... ), 'components'=>array( #... 'user'=>array( 'class' => 'RWebUser', 'allowAutoLogin'=>true, ), 'authManager'=>array( 'class'=>'RDbAuthManager', 'defaultRoles' => array('Guest') // дефолтная роль ), #... ),
Далее создаем таблицы в базе данных mysql из файлов /protected/modules/user/data/schema.mysql.sql и /protected/modules/user/data/schema.sq.
Ура! Мы успешно установили модули. Проверяем. Заходим по ссылке yiitest/?r=user и видим —

По умолчанию при установке модуля создаются 2 пользователя — admin и demo с паролями admin и demo соответственно. Вы можете авторизоваться под admin:admin и посмотреть все прелести данного модуля. Вкраце о них:
- Готовая реализация регистрации, авторизации, восстановления пароля, активации аккаунта;
- Есть механизм дополнительных полей профиля. То есть к профилю пользователя можно безболезненно прикрутить дополнительные поля, например дату рождения, город, телефон и тд. Можно настроить название поля, тип, код, дефолтное значение, регулярное выражение для валидации, навесить свой виджет вместо стандартного инпута и ещё много всякого разного и вкусного;
- Готовый интерфейс администрирования всего модуля (в стиле CRUD).
INSERT INTO `AuthItem` (`name`, `type`, `description`, `bizrule`, `data`) VALUES ('Admin', 2, 'Администратор', NULL, 'N;'), ('Authenticated', 2, 'Зарегистрированный пользователь', NULL, 'N;'), ('Guest', 2, 'Гость', NULL, 'N;'); INSERT INTO `AuthAssignment` (`itemname`, `userid`, `bizrule`, `data`) VALUES ('Admin', '1', NULL, 'N;'), -- цифру 1 нужно заменить на ID администратора (в нашем примере это первый пользователь) ('Authenticated', '2', NULL, 'N;');
Обновляем страницу yiitest/?r=rights, если снова просит авторизоваться под superuser, авторизуемся под пользователем с ID=1 (в нашем примере это admin:admin). И, как говорят в одной замечательной стране, вуаля! Сразу видим интерфейс администрирования. Вкраце о возможностях:
- Можно привязать несколько ролей к одному пользователю;
- Операции группируются;
- Роли могут наследовать разрешения;
- Многое другое.
public function filters(){ return array( #..., 'rights' ); }
На сладкое
Это все конечно очень здорово, но во всей этой схеме закрался небольшой багнебаг (разработчики не предусмотрели, либо я чего-то ещё не изучил). А именно после регистрации вручную придется выставлять пользователю роль «Authenticated». Для этого я написал небольшой костыль. В модуль «user» в папке components создаем файл OnAfterRegistrationBehavior.php со следующим содержимым:
class OnAfterRegistrationBehavior extends CActiveRecordBehavior{ function afterSave($event){ // получаем таблицу в БД $assignmentTable = Yii::app()->getAuthManager()->assignmentTable; // получаем параметры нового пользователя $attr = $event->sender->getAttributes(); // вытаскиваем название роли по умолчанию из настроек модуля rights $defRole = Yii::app()->getModule('rights')->authenticatedName; // добавляем привязку Yii::app()->db->createCommand( "INSERT INTO {$assignmentTable} (`itemname`,`userid`,`bizrule`,`data`) VALUES ('{$defRole}','{$attr['id']}',NULL,'N;')")->execute(); } }
После чего к модели «RegistrationForm» добавляем поведение «OnAfterRegistrationBehavior»
Только после обновления модуля user не забудьте восстановить поведение. Будем надеяться, что разработчики прикрутят events к своим контроллерам, что бы в будущем не пришлось прибегать к таким костылям.public function behaviors(){ return array( 'OnAfterRegistrationBehavior' => array( 'class' => 'application.modules.user.components.OnAfterRegistrationBehavior' ) ); }
Если кто-то знает более изящное решения, буду рад услышать.
Спасибо за внимание.