yakoffka.ru
    грабли, костыли и велосипеды php, css, html, js и прочего

    Создание интернет-витрины на laravel. Часть 4

    laravel Install Role-based Permissions for Laravel 5 Zizaco/entrust

    Капустин Яков

    оглавление

    Добавляем строку '"zizaco/entrust": "5.2.x-dev"' в composer.json и выполняем 'composer update'.

    composer.json:
    01
    02
    03
    04
    05
    06
    07
    08
    09
    10
    11
    12
    13

    ...
    "require-dev": {
      
    "beyondcode/laravel-dump-server""^1.0",
      
    "filp/whoops""^2.0",
      
    "fzaninotto/faker""^1.4",
      
    "mockery/mockery""^1.0",
      
    "nunomaduro/collision""^3.0",
      
    "phpunit/phpunit""^7.5",
      
    "zizaco/entrust""5.2.x-dev"
    },
    ...
    bash:
    vagrant@homestead:~/projects/kk$ composer update 1/11: http://repo.packagist.org/p/provider-latest$80fc4911c3928b4557e6f900b8a0aefa8850143bd5bd7ab4584d8bcd6246d5ac.json 2/11: http://repo.packagist.org/p/provider-2019-01$c513e6d875d69788f884db7fd2982cc795db75b9ddf8110fde5cee9344b28bcb.json 3/11: http://repo.packagist.org/p/provider-2018-10$659580f46d1602b107aecc670586bcef44b1379a83ef2098b1ae0eb103975e0b.json 4/11: http://repo.packagist.org/p/provider-2018$fe9dd57a956b0e8958ca9e3aef1e5a081da8434855a70182a316000481345bc6.json 5/11: http://repo.packagist.org/p/provider-2013$561b6325bf5dfb2079344a1a6707713c2abd6f1380334ca676e168ba7b74bd95.json 6/11: http://repo.packagist.org/p/provider-2019-04$b526daf47a909245f07b259736b481eb378506f2003590c57d74f2b8b8fa32f0.json 7/11: http://repo.packagist.org/p/provider-2017$2a33038313a0e7c25c09697ddc3172ce4f2aafc0330c674dba95ebc41fb04125.json 8/11: http://repo.packagist.org/p/provider-2018-07$e5d5a2bf0411eb2d6c4b4c5a7dfd6e2dbd4ab2b660c436c0fc8c5090e10b2d9a.json 9/11: http://repo.packagist.org/p/provider-2016$7a6af773e314fb45a7b3be00efc5ca6206e799871bbb39935276951d1f95b5b3.json 10/11: http://repo.packagist.org/p/provider-2014$f66fdb4b5eeae27024c59cdbae4def40efd0b88eba7407154b11e97b3311f732.json 11/11: http://repo.packagist.org/p/provider-2015$fd9ea965b06b9cd9d6ea5382ea56f34d107e4317b9e4e87d52c18a30b2a52ea0.json Finished: success: 11, skipped: 0, failure: 0, total: 11 Loading composer repositories with package information Updating dependencies (including require-dev) 1/3: https://codeload.github.com/Zizaco/entrust/legacy.zip/3623cc052937d9e62543402b50f24065720d44b9 2/3: https://codeload.github.com/thephpleague/flysystem/legacy.zip/c5a5097156387970e6f0ccfcdf03f752856f3391 3/3: https://codeload.github.com/briannesbitt/Carbon/legacy.zip/8322b7bd1805be31867c13bf3cdaab948a0dd406 Finished: success: 3, skipped: 0, failure: 0, total: 3 Package operations: 1 install, 2 updates, 0 removals - Updating league/flysystem (1.0.51 => 1.0.52): Loading from cache - Updating nesbot/carbon (2.17.1 => 2.18.0): Loading from cache - Installing zizaco/entrust (5.2.x-dev 3623cc0): Loading from cache Writing lock file Generating optimized autoload files > Illuminate\Foundation\ComposerScripts::postAutoloadDump > @php artisan package:discover --ansi Discovered Package: beyondcode/laravel-dump-server Discovered Package: fideloper/proxy Discovered Package: laravel/tinker Discovered Package: nesbot/carbon Discovered Package: nunomaduro/collision Package manifest generated successfully. vagrant@homestead:~/projects/kk$
    nameFile:
    01
    02
    03
    04
    05
    06
    07
    08
    09
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32

      
    ...
      
    'providers' => [
      ...
        
    /*
        * Package Service Providers...
        */
        
    Zizaco\Entrust\EntrustServiceProvider::class,
      ...

      ],

      
    /*
      |--------------------------------------------------------------------------
      | Class Aliases
      |--------------------------------------------------------------------------
      |
      | This array of class aliases will be registered when this application
      | is started. However, feel free to register as many as you wish as
      | the aliases are "lazy" loaded so they don't hinder performance.
      |
      */

      
    'aliases' => [
        ...
        
    'Entrust'   => Zizaco\Entrust\EntrustFacade::class,

      ],

    ];

    bash:
    vagrant@homestead:~/projects/kk$ php artisan vendor:publish Which provider or tag's files would you like to publish?: [0 ] Publish files from all providers and tags listed below [1 ] Provider: BeyondCode\DumpServer\DumpServerServiceProvider [2 ] Provider: Fideloper\Proxy\TrustedProxyServiceProvider [3 ] Provider: Illuminate\Foundation\Providers\FoundationServiceProvider [4 ] Provider: Illuminate\Mail\MailServiceProvider [5 ] Provider: Illuminate\Notifications\NotificationServiceProvider [6 ] Provider: Illuminate\Pagination\PaginationServiceProvider [7 ] Provider: Laravel\Tinker\TinkerServiceProvider [8 ] Provider: Zizaco\Entrust\EntrustServiceProvider [9 ] Tag: config [10] Tag: laravel-errors [11] Tag: laravel-mail [12] Tag: laravel-notifications [13] Tag: laravel-pagination > 8 Copied File [/vendor/zizaco/entrust/src/config/config.php] To [/config/entrust.php] Publishing complete. vagrant@homestead:~/projects/kk$
    app/Http/Kernel.php:
    01
    02
    03
    04
    05
    06
    07
    08
    09
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19

    ...
    protected 
    $routeMiddleware = [
      
    'auth' => \App\Http\Middleware\Authenticate::class,
      
    'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
      
    'bindings' => \Illuminate\Routing\Middleware\SubstituteBindings::class,
      
    'cache.headers' => \Illuminate\Http\Middleware\SetCacheHeaders::class,
      
    'can' => \Illuminate\Auth\Middleware\Authorize::class,
      
    'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
      
    'signed' => \Illuminate\Routing\Middleware\ValidateSignature::class,
      
    'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
      
    'verified' => \Illuminate\Auth\Middleware\EnsureEmailIsVerified::class,

      
    'role' => \Zizaco\Entrust\Middleware\EntrustRole::class,
      
    'permission' => \Zizaco\Entrust\Middleware\EntrustPermission::class,
      
    'ability' => \Zizaco\Entrust\Middleware\EntrustAbility::class,
    ];
    ...
    bash:
    vagrant@homestead:~/projects/kk$ php artisan entrust:migration ReflectionException : Method Zizaco\Entrust\MigrationCommand::handle() does not exist at /home/vagrant/projects/kk/vendor/laravel/framework/src/Illuminate/Container/BoundMethod.php:142 138| $callback = explode('::', $callback); 139| } 140| 141| return is_array($callback) > 142| ? new ReflectionMethod($callback[0], $callback[1]) 143| : new ReflectionFunction($callback); 144| } 145| 146| /** Exception trace: 1 ReflectionMethod::__construct(Object(Zizaco\Entrust\MigrationCommand), "handle") /home/vagrant/projects/kk/vendor/laravel/framework/src/Illuminate/Container/BoundMethod.php:142 2 Illuminate\Container\BoundMethod::getCallReflector() /home/vagrant/projects/kk/vendor/laravel/framework/src/Illuminate/Container/BoundMethod.php:120 Please use the argument -v to see more details. vagrant@homestead:~/projects/kk$

    Решение найдено здесь.

    В файле 'vendor/zizaco/entrust/src/commands/MigrationCommand.php' меняем метод 'fire()' на 'handle()' и вновь запускаем выполнение команды 'php artisan entrust:migration':

    vendor/zizaco/entrust/src/commands/MigrationCommand.php:
    01
    02
    03
    04
    05
    06
    07
    08
    09
    10
    11
    12
    13

    ...

      
    /**
       * Execute the console command.
       *
       * @return void
       */
      // public function fire() // https://github.com/Zizaco/entrust/issues/826#issuecomment-326168987
      
    public function handle()
      {
    ...
    bash:
    vagrant@homestead:~/projects/kk$ php artisan entrust:migration Tables: roles, role_user, permissions, permission_role A migration that creates 'roles', 'role_user', 'permissions', 'permission_role' tables will be created in database/migrations directory Proceed with the migration creation? [Yes|no] (yes/no) [yes]: > Creating migration... Migration successfully created! vagrant@homestead:~/projects/kk$
    bash:
    vagrant@homestead:~/projects/kk$ php artisan migrate Migrating: 2019_05_21_144017_entrust_setup_tables Illuminate\Database\QueryException : SQLSTATE[HY000]: General error: 1215 Cannot add foreign key constraint (SQL: alter table `role_user` add constraint `role_user_user_id_foreign` foreign key (`user_id`) references `users` (`id`) on delete cascade on update cascade) at /home/vagrant/projects/kk/vendor/laravel/framework/src/Illuminate/Database/Connection.php:664 660| // If an exception occurs when attempting to run a query, we'll format the error 661| // message to include the bindings with SQL, which will make this exception a 662| // lot more helpful to the developer instead of just the database's errors. 663| catch (Exception $e) { > 664| throw new QueryException( 665| $query, $this->prepareBindings($bindings), $e 666| ); 667| } 668| Exception trace: 1 PDOException::("SQLSTATE[HY000]: General error: 1215 Cannot add foreign key constraint") /home/vagrant/projects/kk/vendor/laravel/framework/src/Illuminate/Database/Connection.php:458 2 PDOStatement::execute() /home/vagrant/projects/kk/vendor/laravel/framework/src/Illuminate/Database/Connection.php:458 Please use the argument -v to see more details. vagrant@homestead:~/projects/kk$

    Laravel 5.8 использует большое целое число вместо Integer для своих миграций пользовательских таблиц. см. здесь.

    Заменяем все вхождения '$table->increments' на '$table->bigIncrements' и, на всякий случай, '$table->integer' на '$table->bigInteger' в файле 'database/migrations/2019_05_21_144017_entrust_setup_tables.php'.

    bash:
    vagrant@homestead:~/projects/kk$ php artisan migrate --seed vagrant@homestead:~/projects/kk$ php artisan migrate:refresh --seed Rolling back: 2019_05_20_010314_create_comments_table Rolled back: 2019_05_20_010314_create_comments_table Rolling back: 2019_05_17_163750_create_products_table Rolled back: 2019_05_17_163750_create_products_table Rolling back: 2014_10_12_100000_create_password_resets_table Rolled back: 2014_10_12_100000_create_password_resets_table Rolling back: 2014_10_12_000000_create_users_table Rolled back: 2014_10_12_000000_create_users_table Migrating: 2014_10_12_000000_create_users_table Migrated: 2014_10_12_000000_create_users_table Migrating: 2014_10_12_100000_create_password_resets_table Migrated: 2014_10_12_100000_create_password_resets_table Migrating: 2019_05_17_163750_create_products_table Migrated: 2019_05_17_163750_create_products_table Migrating: 2019_05_20_010314_create_comments_table Migrated: 2019_05_20_010314_create_comments_table Migrating: 2019_05_21_144017_entrust_setup_tables Illuminate\Database\QueryException : SQLSTATE[42S01]: Base table or view already exists: 1050 Table 'roles' already exists (SQL: create table `roles` (`id` bigint unsigned not null auto_increment primary key, `name` varchar(255) not null, `display_name` varchar(255) null, `description` varchar(255) null, `created_at` timestamp null, `updated_at` timestamp null) default character set utf8mb4 collate 'utf8mb4_unicode_ci') at /home/vagrant/projects/kk/vendor/laravel/framework/src/Illuminate/Database/Connection.php:664 660| // If an exception occurs when attempting to run a query, we'll format the error 661| // message to include the bindings with SQL, which will make this exception a 662| // lot more helpful to the developer instead of just the database's errors. 663| catch (Exception $e) { > 664| throw new QueryException( 665| $query, $this->prepareBindings($bindings), $e 666| ); 667| } 668| Exception trace: 1 PDOException::("SQLSTATE[42S01]: Base table or view already exists: 1050 Table 'roles' already exists") /home/vagrant/projects/kk/vendor/laravel/framework/src/Illuminate/Database/Connection.php:458 2 PDOStatement::execute() /home/vagrant/projects/kk/vendor/laravel/framework/src/Illuminate/Database/Connection.php:458 Please use the argument -v to see more details. vagrant@homestead:~/projects/kk$

    Выполняем откат миграций и удаляем оставшиеся в базе таблицы,

    bash:
    vagrant@homestead:~/projects/kk$ php artisan migrate:reset Rolling back: 2019_05_20_010314_create_comments_table Rolled back: 2019_05_20_010314_create_comments_table Rolling back: 2019_05_17_163750_create_products_table Rolled back: 2019_05_17_163750_create_products_table Rolling back: 2014_10_12_100000_create_password_resets_table Rolled back: 2014_10_12_100000_create_password_resets_table Rolling back: 2014_10_12_000000_create_users_table Rolled back: 2014_10_12_000000_create_users_table vagrant@homestead:~/projects/kk$ vagrant@homestead:~/projects/kk$ vagrant@homestead:~/projects/kk$ vagrant@homestead:~/projects/kk$ mysql Welcome to the MySQL monitor. Commands end with ; or \g. Your MySQL connection id is 754 Server version: 5.7.25-0ubuntu0.18.04.2 (Ubuntu) Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved. Oracle is a registered trademark of Oracle Corporation and/or its affiliates. Other names may be trademarks of their respective owners. Type 'help;' or '\h' for help. Type '\c' to clear the current input statement. mysql> use kk_db; Reading table information for completion of table and column names You can turn off this feature to get a quicker startup with -A Database changed mysql> show tables; +-----------------+ | Tables_in_kk_db | +-----------------+ | migrations | | role_user | | roles | +-----------------+ 3 rows in set (0.00 sec) mysql> drop table roles; Query OK, 0 rows affected (0.01 sec) mysql> drop table role_user; Query OK, 0 rows affected (0.02 sec) mysql> exit Bye

    затем комментируем содержимое метода down() в файле миграции, запускаем команду 'php artisan migrate:refresh --seed' и раскомментируем содержимое метода down().

    bash:
    vagrant@homestead:~/projects/kk$ php artisan migrate:refresh --seed Rolling back: 2019_05_21_144017_entrust_setup_tables Rolled back: 2019_05_21_144017_entrust_setup_tables Rolling back: 2019_05_20_010314_create_comments_table Rolled back: 2019_05_20_010314_create_comments_table Rolling back: 2019_05_17_163750_create_products_table Rolled back: 2019_05_17_163750_create_products_table Rolling back: 2014_10_12_100000_create_password_resets_table Rolled back: 2014_10_12_100000_create_password_resets_table Rolling back: 2014_10_12_000000_create_users_table Rolled back: 2014_10_12_000000_create_users_table Migrating: 2014_10_12_000000_create_users_table Migrated: 2014_10_12_000000_create_users_table Migrating: 2014_10_12_100000_create_password_resets_table Migrated: 2014_10_12_100000_create_password_resets_table Migrating: 2019_05_17_163750_create_products_table Migrated: 2019_05_17_163750_create_products_table Migrating: 2019_05_20_010314_create_comments_table Migrated: 2019_05_20_010314_create_comments_table Migrating: 2019_05_21_144017_entrust_setup_tables Migrated: 2019_05_21_144017_entrust_setup_tables Seeding: ProductsTableSeeder Seeding: UsersTableSeeder Database seeding completed successfully. vagrant@homestead:~/projects/kk$
    bash:
    vagrant@homestead:~/projects/kk$ php artisan make:model Role Model created successfully. vagrant@homestead:~/projects/kk$ php artisan make:model Permission Model created successfully. vagrant@homestead:~/projects/kk$

    В инструкции указан файл 'app/models/Role.php'. Создаю 'app/Role.php'. То же самое и с 'app/Permission.php'.

    app/Role.php:
    01
    02
    03
    04
    05
    06
    07
    08
    09
    10
    11
    12

    <?php

    namespace App;

    use 
    Zizaco\Entrust\EntrustRole;

    class 
    Role extends EntrustRole
    {
      
    //
    }
    app/Permission.php:
    01
    02
    03
    04
    05
    06
    07
    08
    09
    10
    11
    12

    <?php

    namespace App;

    use 
    Zizaco\Entrust\EntrustPermission;

    class 
    Permission extends EntrustPermission
    {
      
    //
    }

    Добавление методов roles(), hasRole($name), withRole($name), can($permission) и ability($roles, $permissions, $options) в модели User подключением трейта EntrustUserTrait.

    app/User.php:
    01
    02
    03
    04
    05
    06
    07
    08
    09
    10
    11
    12
    13
    14
    15

    <?php

    namespace App;

    use 
    Illuminate\Notifications\Notifiable;
    use 
    Illuminate\Contracts\Auth\MustVerifyEmail;
    use 
    Illuminate\Foundation\Auth\User as Authenticatable;
    use 
    Zizaco\Entrust\Traits\EntrustUserTrait// upd

    class User extends Authenticatable
    {
      use 
    NotifiableEntrustUserTrait// upd
      
    ...
    bash:
    vagrant@homestead:~/projects/kk$ composer dump-autoload Generating optimized autoload files> Illuminate\Foundation\ComposerScripts::postAutoloadDump > @php artisan package:discover --ansi Discovered Package: beyondcode/laravel-dump-server Discovered Package: fideloper/proxy Discovered Package: laravel/tinker Discovered Package: nesbot/carbon Discovered Package: nunomaduro/collision Package manifest generated successfully. Generated optimized autoload files containing 3575 classes vagrant@homestead:~/projects/kk$

    Для таблиц roles, role_user, permissions и permission_role создадим и опишем RolesTableSeeder, RoleUserTableSeeder, PermissionsTableSeeder и PermissionRoleTableSeeder.

    bash:
    vagrant@homestead:~/projects/kk$ php artisan make:seeder RolesTableSeeder Seeder created successfully. vagrant@homestead:~/projects/kk$ php artisan make:seeder RoleUserTableSeeder Seeder created successfully. vagrant@homestead:~/projects/kk$ php artisan make:seeder PermissionsTableSeeder Seeder created successfully. vagrant@homestead:~/projects/kk$ php artisan make:seeder PermissionRoleTableSeeder Seeder created successfully. vagrant@homestead:~/projects/kk$
    database/seeds/RolesTableSeeder.php:
    01
    02
    03
    04
    05
    06
    07
    08
    09
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44

    <?php

    use Illuminate\Database\Seeder;

    class 
    RolesTableSeeder extends Seeder
    {
      
    /**
       * Run the database seeds.
       *
       * @return void
       */
      
    public function run()
      {
        
    $roles = [
          [
            
    'name' => 'owner',
            
    'display_name' => 'Project Owner',
            
    'description'  => 'The user is the owner of this project. Has all possible rights.',
          ],[
            
    'name' => 'admin',
            
    'display_name' => 'Admin',
            
    'description'  => 'Admin acts within the framework of the rights granted to it by the owner.',
          ],[
            
    'name' => 'manager',
            
    'display_name' => 'Manager',
            
    'description'  => 'Store management.',
          ],[
            
    'name' => 'user',
            
    'display_name' => 'User',
            
    'description'  => 'Plays the role of the buyer.',
          ] 
        ];
     
        foreach (
    $roles as $role){
          
    DB::table('roles')->insert([
            
    'name' => $role['name'],
            
    'display_name' => $role['display_name'],
            
    'description' => $role['description'],
          ]);
        }
      }
    }
    database/seeds/PermissionsTableSeeder.php:
    01
    02
    03
    04
    05
    06
    07
    08
    09
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64

    <?php

    use Illuminate\Database\Seeder;

    class 
    PermissionsTableSeeder extends Seeder
    {
      
    /**
       * Run the database seeds.
       *
       * @return void
       */
      
    public function run()
      {
        
    $permissions = [

          
    /*
          *   ПОРЯДОК СЛЕДОВАНИЯ НЕ НАРУШАТЬ!
          *  используется в database/seeds/PermissionRoleTableSeeder.php
          */

          // permissions for roles
          
    ['group' => 'roles''name' => 'create_roles',  'display_name' => 'Create Roles',   'description' => 'Create the Role', ],
          [
    'group' => 'roles''name' => 'edit_roles',  'display_name' => 'Edit Roles',   'description' => 'Edit the Role',   ],
          [
    'group' => 'roles''name' => 'delete_roles',  'display_name' => 'Delete Roles',   'description' => 'Delete the Role', ],
          [
    'group' => 'roles''name' => 'view_roles',  'display_name' => 'View Roles',   'description'  => 'View the Role',  ],
          
          
    // permissions for permissions
          
    ['group' => 'permissions''name' => 'create_permissions',  'display_name' => 'Create Permissions',   'description' => 'Create the Permission', ],
          [
    'group' => 'permissions''name' => 'edit_permissions',  'display_name' => 'Edit Permissions',   'description' => 'Edit the Permission',   ],
          [
    'group' => 'permissions''name' => 'delete_permissions',  'display_name' => 'Delete Permissions',   'description' => 'Delete the Permission', ],
          [
    'group' => 'permissions''name' => 'view_permissions',  'display_name' => 'View Permissions',   'description'  => 'View the Permission',  ],
          
          
    // permissions for users
          
    ['group' => 'users''name' => 'create_users',  'display_name' => 'Create Users',   'description' => 'Create the User', ],
          [
    'group' => 'users''name' => 'edit_users',  'display_name' => 'Edit Users',   'description' => 'Edit the User',   ],
          [
    'group' => 'users''name' => 'delete_users',  'display_name' => 'Delete Users',   'description' => 'Delete the User', ],
          [
    'group' => 'users''name' => 'view_users',  'display_name' => 'View Users',   'description'  => 'View the User',  ],
          
          
    // permissions for comments
          
    ['group' => 'comments''name' => 'create_comments',  'display_name' => 'Create Comments',   'description' => 'Create the Comment', ],
          [
    'group' => 'comments''name' => 'edit_comments',  'display_name' => 'Edit Comments',   'description' => 'Edit the Comment',   ],
          [
    'group' => 'comments''name' => 'delete_comments',  'display_name' => 'Delete Comments',   'description' => 'Delete the Comment', ],
          [
    'group' => 'comments''name' => 'view_comments',  'display_name' => 'View Comments',   'description'  => 'View the Comment',  ],
          
          
    // permissions for products
          
    ['group' => 'products''name' => 'create_products',  'display_name' => 'Create Products',   'description' => 'Create the Product', ],
          [
    'group' => 'products''name' => 'edit_products',  'display_name' => 'Edit Products',   'description' => 'Edit the Product',   ],
          [
    'group' => 'products''name' => 'delete_products',  'display_name' => 'Delete Products',   'description' => 'Delete the Product', ],
          [
    'group' => 'products''name' => 'view_products',  'display_name' => 'View Products',   'description'  => 'View the Product',  ],
          
        ];
     
        foreach (
    $permissions as $permission){
          
    DB::table('permissions')->insert([
            
    'group' => $permission['group'],
            
    'name' => $permission['name'],
            
    'display_name' => $permission['display_name'],
            
    'description' => $permission['description'],
          ]);
        }
      }
    }
    database/seeds/RoleUserTableSeeder.php:
    01
    02
    03
    04
    05
    06
    07
    08
    09
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38

    <?php

    use Illuminate\Database\Seeder;
    use 
    App\User;

    class 
    RoleUserTableSeeder extends Seeder
    {
      
    /**
       * Run the database seeds.
       *
       * @return void
       */
      
    public function run()
      {
        
    $users User::all();

        foreach (
    $users as $user) {

          if (
    $user->id == 1) {
            
    $role_id 1;
          } elseif (
    $user->id == 2) {
            
    $role_id 2;
          } elseif (
    $user->id == 3) {
            
    $role_id 3;
          } else {
            
    $role_id 4;
          }

          
    DB::table('role_user')->insert([
            
    'user_id' => $user->id,
            
    'role_id' => $role_id,
          ]);

        }
      }
    }
    database/seeds/PermissionRoleTableSeeder.php:
    01
    02
    03
    04
    05
    06
    07
    08
    09
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45

    <?php

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

    class 
    PermissionRoleTableSeeder extends Seeder
    {
      
    /**
       * Run the database seeds.
       *
       * @return void
       */
      
    public function run()
      {
        
    $roles Role::all();
        
    $permissions Permission::all();

        foreach (
    $roles as $role) {

          foreach (
    $permissions as $permission) {

            if (
              
    $role->id == 1
              
    or 
              
    $role->id == and !in_array($permission->id, [123567])
              or
              
    $role->id == and ( $permission->id 12 or in_array($permission->id, [4891012] ) )
              or
              
    in_array($permission->id, [9101620])
              ) {

              
    DB::table('permission_role')->insert([
                
    'permission_id' => $permission->id,
                
    'role_id' => $role->id,
              ]);
            }    
          }

        }

      }
    }

    Добавим по такому случаю побольше пользователей. Хороших и разных.

    database/seeds/UsersTableSeeder.php:
    01
    02
    03
    04
    05
    06
    07
    08
    09
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52

    <?php

    use Illuminate\Database\Seeder;

    class 
    UsersTableSeeder extends Seeder
    {
      
    /**
       * Run the database seeds.
       *
       * @return void
       */
      
    public function run()
      {
        
    DB::table('users')->insert([
          
    'name' => 'Owner Name',
          
    'email' => 'owner@gmail.com',
          
    'password' => bcrypt('111111'),
        ]);

        
    DB::table('users')->insert([
          
    'name' => 'Admin Name',
          
    'email' => 'admin@gmail.com',
          
    'password' => bcrypt('111111'),
        ]);

        
    DB::table('users')->insert([
          
    'name' => 'Manager Name',
          
    'email' => 'manager@gmail.com',
          
    'password' => bcrypt('111111'),
        ]);

        
    DB::table('users')->insert([
          
    'name' => 'User First Name',
          
    'email' => 'user01@gmail.com',
          
    'password' => bcrypt('111111'),
        ]);

        
    DB::table('users')->insert([
          
    'name' => 'User Second Name',
          
    'email' => 'user02@gmail.com',
          
    'password' => bcrypt('111111'),
        ]);

        
    DB::table('users')->insert([
          
    'name' => 'User Third Name',
          
    'email' => 'user03@gmail.com',
          
    'password' => bcrypt('111111'),
        ]);
      }
    }

    Добавление сидов в автопосев с непременным соблюдением очередности.

    database/seeds/DatabaseSeeder.php:
    01
    02
    03
    04
    05
    06
    07
    08
    09
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26

    <?php

    use Illuminate\Database\Seeder;

    class 
    DatabaseSeeder extends Seeder
    {
      
    /**
       * Seed the application's database.
       *
       * @return void
       */
      
    public function run()
      {
        
    $this->call([
          
    ProductsTableSeeder::class,
          
    UsersTableSeeder::class,
          
    // Zizaco/entrust
          
    RolesTableSeeder::class,
          
    PermissionsTableSeeder::class,
          
    RoleUserTableSeeder::class,
          
    PermissionRoleTableSeeder::class,
        ]);
      }
    }

    Запускаем перестроение базы данных.

    bash:
    vagrant@homestead:~/projects/kk$ php artisan migrate:refresh --seed Rolling back: 2019_05_21_144017_entrust_setup_tables Rolled back: 2019_05_21_144017_entrust_setup_tables Rolling back: 2019_05_20_010314_create_comments_table Rolled back: 2019_05_20_010314_create_comments_table Rolling back: 2019_05_17_163750_create_products_table Rolled back: 2019_05_17_163750_create_products_table Rolling back: 2014_10_12_100000_create_password_resets_table Rolled back: 2014_10_12_100000_create_password_resets_table Rolling back: 2014_10_12_000000_create_users_table Rolled back: 2014_10_12_000000_create_users_table Migrating: 2014_10_12_000000_create_users_table Migrated: 2014_10_12_000000_create_users_table Migrating: 2014_10_12_100000_create_password_resets_table Migrated: 2014_10_12_100000_create_password_resets_table Migrating: 2019_05_17_163750_create_products_table Migrated: 2019_05_17_163750_create_products_table Migrating: 2019_05_20_010314_create_comments_table Migrated: 2019_05_20_010314_create_comments_table Migrating: 2019_05_21_144017_entrust_setup_tables Migrated: 2019_05_21_144017_entrust_setup_tables Seeding: ProductsTableSeeder Seeding: UsersTableSeeder Seeding: RolesTableSeeder Seeding: PermissionsTableSeeder Seeding: RoleUserTableSeeder Seeding: PermissionRoleTableSeeder Database seeding completed successfully. vagrant@homestead:~/projects/kk$

    Добавляем в файл отображения примеры использования приложения.

    resources/views/home.blade.php:
    01
    02
    03
    04
    05
    06
    07
    08
    09
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30

    ...
    <!-- 
    Zizaco -->
    @if ( 
    Auth::user()->hasRole(['owner''admin']) )
      <
    p>read usage <a href="https://github.com/Zizaco/entrust#usage">Zizaco/entrust</a></p>
    @endif  

    @
    role('owner')
      <
    p>youre role is owner</p>
    @
    endrole

    @role('admin')
      <
    p>youre role is admin</p>
    @
    endrole

    @role('manager')
      <
    p>youre role is manager</p>
    @
    endrole

    @role('user')
      <
    p>youre role is user</p>
    @
    endrole


    <?php
      
    echo Auth::user()->roles->first()->name;
    ?>
    <!-- /Zizaco -->
    ...

    Логинимся под пользователем owner - и получаем вышеозначенную ошибку. Меняем значение CACHE_DRIVER=file на CACHE_DRIVER=array в '.env', как сказано здесь.

    Рис. 1 ErrorException (E_ERROR) This cache store does not support tagging
    Рис. 1 ErrorException (E_ERROR) This cache store does not support tagging
    Рис. 2 Вывод роли текущего пользователя
    Рис. 2 Вывод роли текущего пользователя
    *.blade.php:
    01
    02
    03
    04
    05
    06
    07
    08
    09
    10
    11
    12
    13
    14
    15

    @permission('edit_products')
      
    Этот блок будет показан пользователям с разрешением edit_products
    @endpermission

    <!-- or -->
    @
    permission('edit_users''delete_users')
      
    Этот блок будет показан пользователям даже с одним из перечисленных в условии разрешением
    @endpermission

    <!-- and -->
    @
    permission(['edit_users''delete_users'], true)
      
    Этот блок будет показан пользователям со всеми перечисленными в условии разрешениями
    @endpermission

    Больше примеров смотри здесь.

    *Controller.php:
    01
    02
    03
    04
    05
    06
    07
    08
    09
    10
    11
    12
    13
    14
    15
    16
    17
    18

    // вернуть 403 ответ, если пользователь не имеет права create_products
    abort_if ( !Auth::user()->can('create_products'), 403 );

    // или так
    abort_if Auth::user()->cannot('create_products'), 403 );

    // добавить пользователю роль с id == 4
    $user->attachRole(4);

    // получить всех пользователей с ролью admin
    $admins User::withRole('admin')->get();

    // добавить мидлваре для всех методов класса
    public function __construct() {
      
    $this->middleware(['auth''permission:view_users']);
    }
    bash:
    vagrant@homestead:~/projects/kk$ php artisan make:controller -r UsersController Controller created successfully. vagrant@homestead:~/projects/kk$
    app/Http/Controllers/UsersController.php:
    001
    002
    003
    004
    005
    006
    007
    008
    009
    010
    011
    012
    013
    014
    015
    016
    017
    018
    019
    020
    021
    022
    023
    024
    025
    026
    027
    028
    029
    030
    031
    032
    033
    034
    035
    036
    037
    038
    039
    040
    041
    042
    043
    044
    045
    046
    047
    048
    049
    050
    051
    052
    053
    054
    055
    056
    057
    058
    059
    060
    061
    062
    063
    064
    065
    066
    067
    068
    069
    070
    071
    072
    073
    074
    075
    076
    077
    078
    079
    080
    081
    082
    083
    084
    085
    086
    087
    088
    089
    090
    091
    092
    093
    094
    095
    096
    097
    098
    099
    100
    101
    102
    103
    104
    105

    <?php

    namespace App\Http\Controllers;
    use 
    Auth;
    use 
    Illuminate\Support\Facades\DB;
    use 
    Illuminate\Http\Request;
    use 
    Illuminate\Support\Facades\Validator;
    use 
    Illuminate\Support\Facades\Hash;

    use 
    App\User;

    class 
    UsersController extends Controller
    {
      public function 
    __construct() {
        
    $this->middleware('auth');
      }

      
    /**
       * Display a listing of the resource.
       *
       * @return \Illuminate\Http\Response
       */
      
    public function index()
      {
        
    abort_if Auth::user()->cannot('view_users'), 403 );
        
    $users User::all();
        return 
    view('users.index'compact('users'));
      }

      
    /**
       * Display the specified resource.
       *
       * @param  int  $id
       * @return \Illuminate\Http\Response
       */
      
    public function show($id)
      {
        
    abort_if Auth::user()->cannot('view_users'), 403 );
        
    $user User::findOrFail($id);
        return 
    view('users.show'compact('user'));
      }

      
    /**
       * Show the form for editing the specified resource.
       *
       * @param  int  $id
       * @return \Illuminate\Http\Response
       */
      
    public function edit($id)
      {
        
    abort_if ( !Auth::user()->can('edit_users'), 403 );
        
    $user User::findOrFail($id);
        return 
    view('users.edit'compact('user'));
      }


      
    /**
       * Update the specified resource in storage.
       *
       * @param  \Illuminate\Http\Request  $request
       * @param  int  $id
       * @return \Illuminate\Http\Response
       */
      
    public function update(User $user)
      {
        
    abort_if ( !Auth::user()->can('edit_users'), 403 );

        
    $validator Validator::make (request()->all(), [
          
    'name' => 'required|string|max:255',
          
    'email' => 'required|string|email|max:255'// |unique:users
          
    'password' => 'required|string|min:6|max:255'// confirmed?
        
    ]);

        if (
    $validator->fails()) {
          return 
    back()->withErrors($validator)->withInput();
        }

        if ( !
    Hash::check(request('password'),$user->password )) {
          return 
    back()->withErrors(['failed password'])->withInput();
        }

        
    $user->update([
          
    'name' => request('name'),
          
    'email' => request('email'),
        ]);

        return 
    redirectroute('usersShow', ['user' => $user]));
      }

      
    /**
       * Remove the specified resource from storage.
       *
       * @param  int  $id
       * @return \Illuminate\Http\Response
       */
      
    public function destroy(User $user)
      {
        
    abort_if ( !Auth::user()->can('edit_users'), 403 );
        
    $user->delete();
        return 
    redirectroute('users'));
      }

    }

    Роуты для UsersController.

    routes/web.php:
    01
    02
    03
    04
    05
    06
    07
    08
    09
    10
    11
    12

    ...

    /* users*/
    Route::get('/users''UsersController@index')->name('users');
    Route::get('/users/create''UsersController@create')->name('usersCreate');
    Route::get('/users/{user}''UsersController@show')->name('usersShow');
    Route::post('/users''UsersController@store')->name('usersStore');
    Route::get('/users/edit/{user}''UsersController@edit')->name('usersEdit');
    Route::patch('/users/{user}''UsersController@update')->name('usersUpdate');
    Route::delete('/users/{user}''UsersController@destroy')->name('usersDestroy');

    Добавляем файлы отображения:

    resources/views/users/index.blade.php:
    01
    02
    03
    04
    05
    06
    07
    08
    09
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75

    @extends('layouts.app')

    @
    section('title')
    users
    @endsection

    @section('content')
    <
    div class="container">

      <
    h1>List of users</h1>
      
      <
    table class="blue_table">
        <
    tr>
          <
    th>#</th>
          
    <th>id</th>
          <
    th>img</th>
          <
    th>name</th>
          <
    th>email</th>
          <
    th>role</th>
          <
    th>created_at</th>
          <
    th>updated_at</th>
          <
    th>actions</th>
        </
    tr>

        @foreach(
    $users as $i=>$user)

        <
    tr>
          <
    td>{{ $i+}}</td>
          <
    td>{{ $user->id }}</td>
          <
    td><img src="{{ asset('storage') }}/images/default/user_default.png" alt="no image" width="75px"></td>
          <
    td>{{ $user->name }}</td>
          <
    td>{{ $user->email }}</td>
          <
    td>{{ $user->roles->first()->name }}</td>
          <
    td>{{ $user->created_at ?? '-' }}</td>
          <
    td>{{ $user->updated_at ?? '-' }}</td>
          <
    td>
            <
    div class="td user_buttons row">

              <
    div class="col-sm-4">
                <
    a href="{{ route('usersShow', ['user' => $user->id]) }}" class="btn btn-outline-primary">
                  <
    class="fas fa-eye"></i>
                </
    a>
              </
    div>

              <
    div class="col-sm-4">
                <
    a href="{{ route('usersEdit', ['user' => $user->id]) }}" class="btn btn-outline-success">
                  <
    class="fas fa-pen-nib"></i>
                </
    a>
              </
    div>

              <
    div class="col-sm-4">
                <
    form action="{{ route('usersDestroy', ['user' => $user->id]) }}" method='POST'>
                  @
    csrf

                  
    @method('DELETE')

                  <
    button type="submit" class="btn btn-outline-danger">
                  <
    class="fas fa-trash"></i>
                  </
    button>
                </
    form>
              </
    div>

            </
    div>
          </
    td>
        </
    tr>

        @endforeach

      </
    table>


    </
    div>
    @
    endsection
    resources/views/users/show.blade.php:
    01
    02
    03
    04
    05
    06
    07
    08
    09
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71

    @extends('layouts.app')

    @
    section('title')
    user
    @endsection

    @section('content')
    <
    div class="container">

      <
    h1>show user {{ $user->name }}</h1>
      
      <
    div>{{ $user->id }}</div>
      <
    div><img src="{{ asset('storage') }}/images/default/user_default.png" alt="no image" width="75px"></div>
      <
    div>{{ $user->name }}</div>
      <
    div>{{ $user->email }}</div>
      <
    div>{{ $user->roles->first()->name }}</div>
      <
    div>{{ $user->created_at ?? '-' }}</div>
      <
    div>{{ $user->updated_at ?? '-' }}</div>

      @
    permission(['edit_users''delete_users'], true)

        <
    div>
          <
    div class="div user_buttons row">

            <
    div class="col-sm-6">
              <
    a href="{{ route('usersEdit', ['user' => $user->id]) }}" class="btn btn-outline-success">
                <
    class="fas fa-pen-nib"></i>
              </
    a>
            </
    div>

            <
    div class="col-sm-6">
              <
    form action="{{ route('usersDestroy', ['user' => $user->id]) }}" method='POST'>
                @
    csrf

                
    @method('DELETE')

                <
    button type="submit" class="btn btn-outline-danger">
                <
    class="fas fa-trash"></i>
                </
    button>
              </
    form>
            </
    div>

          </
    div>
        </
    div>

      @
    endpermission


      
    <!-- @ permission('edit_users') -->
      @if( 
    Auth::user()->can('edit_users') and Auth::user()->cannot('delete_users'))

        <
    div>
          <
    div class="div user_buttons row">

            <
    div class="col-sm-12">
              <
    a href="{{ route('usersEdit', ['user' => $user->id]) }}" class="btn btn-outline-success">
                <
    class="fas fa-pen-nib"></i>
              </
    a>
            </
    div>

          </
    div>
        </
    div>

      <!-- @ 
    endpermission -->
      @endif


    </
    div>
    @
    endsection
    resources/views/users/edit.blade.php:
    01
    02
    03
    04
    05
    06
    07
    08
    09
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45

    @extends('layouts.app')

    @
    section('title')
    edit profile
    @endsection

    @section('content')
    <
    div class="container">

      <
    h1>edit profile {{ $user->name }}</h1>
      
      <
    div><img src="{{ asset('storage') }}/images/default/user_default.png" alt="no image" width="75px"></div>

      <
    form method="POST" 
        
    action="{{ route('usersUpdate', ['user' => $user->id]) }}" 
        
    enctype="multipart/form-data">

        @
    csrf

        
    @method('PATCH')

        <
    div class="form-group">
          <
    label for="name">name user</label>
          <
    input type="text" id="name" name="name" class="form-control" 
            
    value="{{ old('name') ?? $user->name }}" required>
        </
    div>

        <
    div class="form-group">
          <
    label for="email">email user</label>
          <
    input type="email" id="email" name="email" class="form-control" 
            
    value="{{ old('email') ?? $user->email }}">
        </
    div>

        <
    div class="form-group">
          <
    label for="name">password user</label>
          <
    input type="password" id="password" name="password" class="form-control" required>
        </
    div>

        <
    button type="submit" class="btn btn-primary form-control">edit profile!</button>

      </
    form>
    </
    div>
    @
    endsection
    Рис. 3 Список пользователей index users
    Рис. 3 Список пользователей index users
    Рис. 4 Список ролей index roles
    Рис. 4 Список ролей index roles
    Рис. 5 Отображение роли Admin
    Рис. 5 Отображение роли Admin

    Исходники можно скачать здесь..

    upd: При попытке удаления роли

    app/Http/Controllers/RolesController.php:
    1
    2
    3
    4
    5
    6
    7
    8

    public function destroy(Role $role)
    {
      
    $role->forceDelete();
      
    // $role->delete();
      
    return redirect()->route('roles');
    }

    браузер выдает ошибку 'Class name must be a valid object or a string'.

    Первый вариант (Решение найдено здесь):

    app/Role.php:
    01
    02
    03
    04
    05
    06
    07
    08
    09
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24

    <?php

    namespace App;

    use 
    Zizaco\Entrust\EntrustRole;
    use 
    Illuminate\Support\Facades\Config// upd

    class Role extends EntrustRole
    {

      ...

      public function 
    users()// upd
      
    {
        return 
    $this->belongsToMany(
          
    Config::get('auth.providers.users.model'), 
          
    Config::get('entrust.role_user_table'), 
          
    Config::get('entrust.role_foreign_key'), 
          
    Config::get('entrust.user_foreign_key'));
      }

    }

    Второй вариант элегантнее (Решение найдено здесь):

    app/Role.php:
    01
    02
    03
    04
    05
    06
    07
    08
    09
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24

    <?php

    namespace App;

    use 
    Zizaco\Entrust\EntrustRole;

    class 
    Role extends EntrustRole
    {

      ...

      
    /**
      * Many-to-Many relations with the user model.
      *
      * @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
      */
      
    public function users()
      {
        return 
    $this->belongsToMany(User::class);
      }

    }