Слава Україні!

Laravel. Роли и Права. Часть 1

Laravel. Роли и Права. Подготовка БД, миграции, сидеры
15-го травня 2023, 5:51

Генерация Моделей и Миграций

В этом разделе мы создадим две новые модели под названием Role и Permission вместе с их миграциями. Для этого мы запустим две нижеприведенные команды в терминале командной строки.


php artisan make:model Role -m
php artisan make:model Permission -m

Флаг -m позволит генерировать миграцию вместе с моделью. Откроем файлы миграции и обновим их в соответствии со структурой таблицы базы данных, которую мы хотим реализовать.

Откройте файл миграции Роли в папке database/migrations и вставьте в него.


use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

class CreateRolesTable extends Migration
{
    /**
    * Run the migrations.
    *
    * @return void
    */
    public function up()
    {
        Schema::create('roles', function (Blueprint $table) {
            $table->bigIncrements('id');
            $table->string('name');
            $table->string('slug');
            $table->timestamps();
        });
    }
    /**
    * Reverse the migrations.
    *
    * @return void
    */
    public function down()
    {
        Schema::dropIfExists('roles');
    }
}

Мы просто добавили поля name и slug. Теперь откройте файл миграции Прав и вставьте в него.

 
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

class CreatePermissionsTable extends Migration
{
    /**
    * Run the migrations.
    *
    * @return void
    */
    public function up()
    {
        Schema::create('permissions', function (Blueprint $table) {
            $table->bigIncrements('id');
            $table->string('name');
            $table->string('slug');
            $table->timestamps();
        });
    }
    /**
    * Reverse the migrations.
    *
    * @return void
    */
    public function down()
    {
        Schema::dropIfExists('permissions');
    }
}

Так же, как и в предыдущей миграции, мы добавили два поля name и slug. Всё просто.

Добавление необходимых сводных таблиц

Перед миграцией созданных таблиц, давайте определим некоторые отношения, которые мы хотели бы реализовать для Ролей и Прав.

  • Пользователь может иметь Права
  • Пользователь может иметь Роли
  • Роль может иметь Права

Для этих трех отношений нам нужно добавить три сводные таблицы, чтобы создать отношение «Многие ко Многим» между моделями User, Role и Permission.

Давайте создадим миграции для этих сводных таблиц. Сначала мы создадим таблицу для связи между Пользователем и Правами.


php artisan make:migration create_users_permissions_table

Откройте только что созданный файл create_users_permissions_table и скопируйте в него.

 
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

class CreateUsersPermissionsTable extends Migration
{
    /**
    * Run the migrations.
    *
    * @return void
    */
    public function up()
    {
        Schema::create('users_permissions', function (Blueprint $table) {
            $table->unsignedBigInteger('user_id');
            $table->unsignedBigInteger('permission_id');
            $table->foreign('user_id')->references('id')->on('users')
                ->onDelete('cascade');
            $table->foreign('permission_id')->references('id')->on('permissions')
                ->onDelete('cascade');
            $table->primary(['user_id','permission_id']);
        });
    }
    /**
    * Reverse the migrations.
    *
    * @return void
    */
    public function down()
    {
        Schema::dropIfExists('users_permissions');
    }
}

В этой миграции мы определили два столбца user_id и permission_id с внешними ключами в соответствующих таблицах. Плюс, мы определили первичные ключи для этих двух полей.

Далее мы создадим ссылку между таблицами Пользователей и Ролей.


php artisan make:migration create_users_roles_table

Откройте созданный файл миграции create_users_roles_table и скопируйте в него.

 
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

class CreateUsersRolesTable extends Migration
{
    /**
    * Run the migrations.
    *
    * @return void
    */
    public function up()
    {
        Schema::create('users_roles', function (Blueprint $table) {
            $table->unsignedBigInteger('user_id');
            $table->unsignedBigInteger('role_id');
            $table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
            $table->foreign('role_id')->references('id')->on('roles')->onDelete('cascade');
            $table->primary(['user_id','role_id']);
        });
    }
    /**
    * Reverse the migrations.
    *
    * @return void
    */
    public function down()
    {
        Schema::dropIfExists('users_roles');
    }
}

Аналогично предыдущей миграции, у нас также есть два поля user_id и role_id с внешними ключами в соответствующих таблицах и первичными ключами.

Теперь мы создадим сводную таблицу между Ролями и Правами.


php artisan make:migration create_roles_permissions_table

Откройте файл миграции create_roles_permissions_table и скопируйте в него.

 
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

class CreateRolesPermissionsTable extends Migration
{
    /**
    * Run the migrations.
    *
    * @return void
    */
    public function up()
    {
        Schema::create('roles_permissions', function (Blueprint $table) {
            $table->unsignedBigInteger('role_id');
            $table->unsignedBigInteger('permission_id');
            $table->foreign('role_id')->references('id')->on('roles')->onDelete('cascade');
            $table->foreign('permission_id')->references('id')->on('permissions')->onDelete('cascade');
            $table->primary(['role_id','permission_id']);
        });
    }
    /**
    * Reverse the migrations.
    *
    * @return void
    */
    public function down()
    {
        Schema::dropIfExists('roles_permissions');
    }
}

В этой миграции мы определили два поля role_id и permission_id с внешним и первичным ключами.

Теперь у нас есть все необходимые таблицы базы данных, пора начать миграцию.


php artisan migrate

Если все прошло успешно, то вы увидите в вашей базе данных таблицы roles, permissions и три сводные таблицы.

Добавление сидеров

Для быстрого тестирования мы сделаем несколько классов Seed, которые добавят в ваши таблицы несколько фиктивных данных.


php artisan make:seeder PermissionSeeder
php artisan make:seeder RoleSeeder
php artisan make:seeder UserSeeder

Откройте класс RoleSeeder и скопируйте в него.

 
use App\Models\Role;
use Illuminate\Database\Seeder;

class RoleSeeder extends Seeder
{
    /**
     * Run the database seeds.
     *
     * @return void
     */
    public function run()
    {
        $manager = new Role();
        $manager->name = 'Project Manager';
        $manager->slug = 'project-manager';
        $manager->save();
        $developer = new Role();
        $developer->name = 'Web Developer';
        $developer->slug = 'web-developer';
        $developer->save();
    }
}

Откройте класс PermissionSeeder и скопируйте в него.


use App\Models\Permission;
use Illuminate\Database\Seeder;

class PermissionSeeder extends Seeder
{
    /**
     * Run the database seeds.
     *
     * @return void
     */
    public function run()
    {
        $manageUser = new Permission();
        $manageUser->name = 'Manage users';
        $manageUser->slug = 'manage-users';
        $manageUser->save();
        $createTasks = new Permission();
        $createTasks->name = 'Create Tasks';
        $createTasks->slug = 'create-tasks';
        $createTasks->save();
    }
}

Далее, в классе UserSeeder мы создадим несколько Пользователей и добавим к ним Роли и Права.


use App\Models\Role;
use App\Models\User;
use App\Models\Permission;
use Illuminate\Database\Seeder;

class UserSeeder extends Seeder
{
    /**
     * Run the database seeds.
     *
     * @return void
     */
    public function run()
    {
        $developer = Role::where('slug','web-developer')->first();
        $manager = Role::where('slug', 'project-manager')->first();
        $createTasks = Permission::where('slug','create-tasks')->first();
        $manageUsers = Permission::where('slug','manage-users')->first();
        $user1 = new User();
        $user1->name = 'Jhon Deo';
        $user1->email = 'jhon@deo.com';
        $user1->password = bcrypt('secret');
        $user1->save();
        $user1->roles()->attach($developer);
        $user1->permissions()->attach($createTasks);
        $user2 = new User();
        $user2->name = 'Mike Thomas';
        $user2->email = 'mike@thomas.com';
        $user2->password = bcrypt('secret');
        $user2->save();
        $user2->roles()->attach($manager);
        $user2->permissions()->attach($manageUsers);
    }
}

Теперь, когда у нас есть три готовых сида, давайте обновим класс DatabaseSeeder, как показано ниже.


use Illuminate\Database\Seeder;

class DatabaseSeeder extends Seeder
{
    /**
     * Seed the application's database.
     *
     * @return void
     */
    public function run()
    {
        $this->call(RoleSeeder::class);
        $this->call(PermissionSeeder::class);
        $this->call(UserSeeder::class);
    }
}

Чтобы сохранить данные в базе данных, выполните в терминале следующую команду.


php artisan db:seed

Важлива інформація

Міністерство оборони
України
з 24.02 по 07.02
втрати противника
орієнтовно склали:
846650 ( +1340 ) особового складу
9975 ( +10 ) танків
20755 ( +18 ) бойових бронемашин
22785 ( +32 ) артилерійських систем
1271 ( +0 ) РСЗВ
1056 ( +1 ) засоби ППО
369 ( +0 ) літаків
331 ( +0 ) гелікоптерів
36307 ( +96 ) автомобільної техніки
28 ( +0 ) кораблі / катери
3054 ( +0 ) крилаті ракети
24301 ( +116 ) БПЛА
3738 ( +1 ) спец. техніки
4 ( +0 ) установок ОТРК/ТРК
1 ( +0 ) підводні човни