Если вы когда-нибудь делали админку, где одним можно всё, а другим — только смотреть, вы уже сталкивались с проблемой прав. В Yii2 есть встроенный RBAC — механизм ролей и разрешений. Но стандартного набора часто не хватает: нужны условия, иерархия, кэширование. В этой статье я расскажу, как собрать расширенную систему RBAC, которая не превратится в кашу из проверок.
Что такое RBAC и зачем его расширять
RBAC (Role-Based Access Control) — это когда доступ выдаётся не напрямую пользователю, а через роль. Например, роль «редактор» может редактировать статьи, а «админ» — всё. В Yii2 RBAC реализован через компонент authManager. По умолчанию он хранит роли и разрешения в PHP-файлах или в базе данных.
Стандартный RBAC хорош для простых случаев. Но как только появляются правила вроде «редактор может редактировать только свои статьи» или «менеджер видит заказы только своего отдела», встроенных возможностей не хватает. Приходится либо плодить роли, либо писать костыли. Расширенный RBAC решает это через правила (rules) и иерархию.
Настройка authManager в Yii2
Для начала убедимся, что в конфиге приложения подключён authManager с хранением в БД. Это удобнее, чем файлы, потому что роли можно менять на лету.
// config/web.php
return [
'components' => [
'authManager' => [
'class' => 'yii\rbac\DbManager',
// 'cache' => 'cache', // можно включить кэширование
],
// ...
],
];
После этого нужно создать таблицы. В Yii2 есть миграция, которая создаёт четыре таблицы: auth_rule, auth_item, auth_item_child, auth_assignment. Запустите:
yii migrate --migrationPath=@yii/rbac/migrations
Теперь можно создавать роли и разрешения через код или через веб-интерфейс (если используете расширение yii2-admin). Но мы пойдём глубже — напишем свои правила.
Создание собственных правил (Rules)
Правила в RBAC — это классы, которые проверяют, имеет ли пользователь доступ к операции в конкретном контексте. Например, правило «автор может редактировать свою статью».
Создадим правило AuthorRule. Оно будет проверять, что user_id текущего пользователя совпадает с author_id статьи.
namespace app\rbac;
use yii\rbac\Rule;
class AuthorRule extends Rule
{
public $name = 'isAuthor';
public function execute($user, $item, $params)
{
// $params['post'] должен быть передан при проверке
return isset($params['post']) ? $params['post']->author_id == $user : false;
}
}
Теперь зарегистрируем это правило в authManager и привяжем к разрешению updatePost.
$auth = Yii::$app->authManager;
// Создаём правило
$rule = new \app\rbac\AuthorRule();
$auth->add($rule);
// Создаём разрешение с этим правилом
$updatePost = $auth->createPermission('updatePost');
$updatePost->description = 'Редактировать статью';
$updatePost->ruleName = $rule->name;
$auth->add($updatePost);
Теперь при проверке Yii::$app->user->can('updatePost', ['post' => $post]) будет вызвано наше правило. Если пользователь — автор, доступ разрешён.
Иерархия ролей и наследование
Роли могут наследовать разрешения и другие роли. Например, роль «админ» наследует все разрешения «редактора». Это делается через addChild.
$admin = $auth->createRole('admin');
$auth->add($admin);
$editor = $auth->createRole('editor');
$auth->add($editor);
// Админ наследует редактора
$auth->addChild($admin, $editor);
// Редактор наследует разрешение updatePost
$auth->addChild($editor, $updatePost);
Теперь если пользователь имеет роль admin, он автоматически может всё, что может editor, включая updatePost с правилом.
assign(), а не прописывайте их вручную в БД. Это гарантирует, что кэш RBAC обновится корректно.
Кэширование и производительность
RBAC в Yii2 может кэшировать иерархию ролей. Если у вас много проверок на каждом запросе, кэш обязателен. Включите его в конфиге:
'authManager' => [
'class' => 'yii\rbac\DbManager',
'cache' => 'cache', // компонент кэша
],
Но помните: при изменении ролей или правил кэш нужно сбрасывать. DbManager делает это автоматически, если вы используете его методы add, remove и т.д. Если лезете в БД напрямую — сбрасывайте кэш вручную.
Также избегайте избыточных проверок. Например, не вызывайте can() в цикле для каждой записи. Лучше заранее получить список разрешённых ID или использовать find() с условием.
Практические советы и лайфхаки
- Используйте константы для имён ролей и разрешений. Так вы не ошибётесь в строке
'admin'и легко найдёте все использования. - Не привязывайте роли к ID пользователя напрямую. Лучше используйте
auth_assignment— это гибче. - Для сложных условий создавайте отдельные правила. Не пытайтесь запихнуть всю логику в одно правило — будет каша.
- Проверяйте права на уровне контроллера и представления. В Yii2 есть
AccessControlфильтр, но для тонких проверок используйтеYii::$app->user->can()в коде. - Документируйте роли и правила. Через полгода вы забудете, что делает правило
isAuthor. Ведите таблицу.
Вот пример таблицы для документирования ролей:
| Роль | Наследует | Разрешения | Правила |
|---|---|---|---|
| admin | editor, viewer | все | — |
| editor | viewer | createPost, updatePost | isAuthor |
| viewer | — | viewPost | — |
Ещё один лайфхак: для проверки прав в представлениях используйте хелпер. Например, создайте метод can($permission, $params = []) в базовом контроллере, который проксирует вызов к Yii::$app->user->can(). Это упростит код.
Что в итоге
Расширенный RBAC в Yii2 — это не так сложно, как кажется. Главное — правильно настроить authManager, создать правила для контекстных проверок и не забывать про кэш. Используйте иерархию ролей, документируйте всё и не плодите лишние сущности. Тогда система прав будет гибкой и понятной.
Начните с малого: добавьте одно правило для «своих» записей. Уверен, вам понравится, как это упрощает жизнь.
Студия WNDER


