Laravelでユーザーごとの権限を管理するlaravel-permissionをインストールして使用する導入部分を紹介します。
使用しているのは Laravel5.6 と Mysql, nginx です。
● Laravel Permission
1. Laravelのテストアプリの作成
permission_appというテストアプリを作成します。
laravel new permission_app
2. DB作成と .env へDB情報を保存
DB作成は phpmyadmin などで作成してください。
その後 .env に接続情報を書き込みます
.env
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=<YOUR-DB-NAME>
DB_USERNAME=<YOUR-USER-NAME>
DB_PASSWORD=<YOUR-PASSWORD>
3. authのインストールとDBマイグレーション
php artisan make:auth
php artisan migrate
4. nginxの設定 (不要な方は飛ばしてください)
新たにバーチャルホストを作成します。
設定ファイル「permissionapp.conf」を新規作成します。
vi /etc/nginx/conf.d/permissionapp.conf
permissionapp.conf を下記の内容で保存
server {
listen 80;
server_name permissionapp.local;
location / {
root /var/www/html/la/permission_app/public;
index index.php index.html index.htm;
try_files $uri $uri/ /index.php$is_args$args;
}
location ~ \.php$ {
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME /var/www/html/la/permission_app/public/$fastcgi_script_name;
include fastcgi_params;
}
}
5. hosts へサーバ名をセット(不要な方は飛ばしてください)
hosts に下記の内容を追記します。
IPアドレス「192.168.1.99」は適宜書き換えてください。
192.168.1.99 permissionapp.local
6. アプリへアクセス
http://permissionapp.local/
へアクセスして一通りユーザー登録などの動作を確認します。
● Laravel-Permission のインストール
1. laravel/passport , laravel-permission を composerからインストールする
composer require spatie/laravel-permission
2. config/app.phpに追記
config/app.php (163行目あたり)
'providers' => [
// ...
Spatie\Permission\PermissionServiceProvider::class,
];
3. app/Http/Kernel.php に追記
app/Http/Kernel.php(61行目あたり)
protected $routeMiddleware = [
....
'role' => \Spatie\Permission\Middlewares\RoleMiddleware::class,
'permission' => \Spatie\Permission\Middlewares\PermissionMiddleware::class,
]
....
3. DBテーブルのマイグレーション
artisanコマンドで マイグレーションファイルを生成します
php artisan vendor:publish --provider="Spatie\Permission\PermissionServiceProvider" --tag="migrations"
次のようなファイルが生成されます
./database/migrations/2020_03_06_211512_create_permission_tables.php
2020_03_06_211512_create_permission_tables.php の中にDBテーブルを作成するコードが記述されます。
作成されるテーブルは次の5つ
permissions
roles
model_has_permissions
model_has_roles
role_has_permissions
4. コンフィグファイルのマイグレーション
php artisan vendor:publish --provider="Spatie\Permission\PermissionServiceProvider" --tag="config"
次の1ファイルが作成されます
./config/permission.php
5. DBテーブルの作成
php artisan migrate
DBテーブルが作成されます。
● 権限の設定
例として次のような権限で設定を行いたいと思います。
(権限はメソッドごとに設定してもいいですし、クラスごとに設定してもいいと思います。ここでは簡単に3段階の権限としています)
役割「グループ」(Role) | 持つ権限(Permission) |
---|---|
admin | admin_permission , manager_permission , staff_permission |
manager | manager_permission , staff_permission |
staff | staff_permission |
● DBデータの作成
1. PermissionTableSeeder.php
php artisan make:seeder PermissionTableSeeder
app/database/seeds/PermissionTableSeeder.php
<?php
use Illuminate\Database\Seeder;
use Spatie\Permission\Models\Permission;
class PermissionTableSeeder extends Seeder
{
public function run()
{
$permissions = [
'admin_permission',
'manager_permission',
'staff_permission',
];
foreach ($permissions as $permission) {
Permission::create(['name' => $permission]);
}
}
}
2. RoleTableSeeder.php
php artisan make:seeder RoleTableSeeder
app/database/seeds/RoleTableSeeder.php
use Illuminate\Database\Seeder;
use Spatie\Permission\Models\Role;
class RoleTableSeeder extends Seeder
{
public function run()
{
$roles = [
'admin',
'manager',
'staff',
];
foreach ($roles as $role) {
Role::create(['name' => $role]);
}
}
}
3. RoleHasPermissionTableSeeder.php
php artisan make:seeder RoleHasPermissionTableSeeder
app/database/seeds/RoleHasPermissionTableSeeder.php
<?php
use Illuminate\Database\Seeder;
use Spatie\Permission\Models\Role;
class RoleHasPermissionTableSeeder extends Seeder
{
public function run()
{
// admin
$permissions = [
'admin_permission',
'manager_permission',
'staff_permission',
];
$role = Role::findByName('admin');
$role->givePermissionTo($permissions);
// manager
$permissions = [
'manager_permission',
'staff_permission',
];
$role = Role::findByName('manager');
$role->givePermissionTo($permissions);
// staff
$permissions = [
'staff_permission',
];
$role = Role::findByName('staff');
$role->givePermissionTo($permissions);
}
}
4. UserTableSeeder.php
php artisan make:seeder UserTableSeeder
app/database/seeds/UserTableSeeder.php
use App\User;
use Illuminate\Database\Seeder;
class UserTableSeeder extends Seeder
{
public function run()
{
// admin
$user = User::create([
'name' => '管理 太郎',
'email' => 'admin@localhost',
'password' => Hash::make('admin'),
]);
$user->assignRole('admin');
// manager
$user = User::create([
'name' => 'マネージャー大森',
'email' => 'manager@localhost',
'password' => Hash::make('manager'),
]);
$user->assignRole('manager');
// staff
$user = User::create([
'name' => 'スタッフ 花子',
'email' => 'staff@localhost',
'password' => Hash::make('staff'),
]);
$user->assignRole('staff');
}
}
5. シーダーの実行
php artisan db:seed --class=PermissionTableSeeder
php artisan db:seed --class=RoleTableSeeder
php artisan db:seed --class=RoleHasPermissionTableSeeder
php artisan db:seed --class=UserTableSeeder
OFF php artisan db:seed –class=ModelHasRoleTableSeeder OFF
もし class not foundエラーが出る場合は
composer dump-autoload
を実行してから再度実行すること。
● メソッド一覧
Permission
public static create(array $attributes = [])
public roles(): BelongsToMany
public users(): MorphToMany
public static findByName(string $name, $guardName = null): PermissionContract
public static findById(int $id, $guardName = null): PermissionContract
public static findOrCreate(string $name, $guardName = null): PermissionContract
protected static getPermissions(): Collection
Role
public static create(array $attributes = [])
public permissions(): BelongsToMany
public users(): MorphToMany
public static findByName(string $name, $guardName = null): RoleContract
public static findById(int $id, $guardName = null): RoleContract
public static findOrCreate(string $name, $guardName = null): RoleContract
public hasPermissionTo($permission): bool
Userモデルなど既存のモデルに追加される拡張メソッド
use HasRoles; で拡張されるメソッド
use Spatie\Permission\Traits\HasRoles;
class User extends Authenticatable
{
use HasRoles;
..........
public static bootHasRoles()
public roles(): MorphToMany
public scopeRole(Builder $query, $roles): Builder
public assignRole(...$roles)
public removeRole($role)
public syncRoles(...$roles)
public hasRole($roles): bool
public hasAnyRole($roles): bool
public hasAllRoles($roles): bool
public getDirectPermissions(): Collection
public getRoleNames(): Collection
protected getStoredRole($role): Role
protected convertPipeToArray(string $pipeString)
use HasPermissions; で拡張されるメソッド
use Spatie\Permission\Traits\HasPermissions;
class User extends Authenticatable
{
use HasPermissions;
..........
public static bootHasPermissions()
static::deleting( ($model) {
public permissions(): MorphToMany
public scopePermission(Builder $query, $permissions): Builder
protected convertToPermissionModels($permissions): array
public hasPermissionTo($permission, $guardName = null): bool
public hasAnyPermission(...$permissions): bool
public hasAllPermissions(...$permissions): bool
protected hasPermissionViaRole(Permission $permission): bool
public hasDirectPermission($permission): bool
public getPermissionsViaRoles(): Collection
public getAllPermissions(): Collection
public givePermissionTo(...$permissions)
public syncPermissions(...$permissions)
public revokePermissionTo($permission)
protected getStoredPermission($permissions)
protected ensureModelSharesGuard($roleOrPermission)
protected getGuardNames(): Collection
protected getDefaultGuardName(): string
public forgetCachedPermissions()
● Bladeビューでの権限(Permission)判定
次のようにして blade テンプレート内で権限(Permission)を判別することができます。通常こちらを使用すると思います。
<p>
@can('admin_permission')
admin_permission を持っています <br>
@endcan
@can('manager_permission')
manager_permission を持っています <br>
@endcan
@can('staff_permission')
staff_permission を持っています <br>
@endcan
</p>
● Bladeビューでのロール(Role)判定
ロール(Role)を判別したいときはこちらを使用します
<p>
@role('admin')
あなたのロールは admin です<br>
@endrole
@role('manager')
あなたのロールは manager です<br>
@endrole
@role('staff')
あなたのロールは staff です<br>
@endrole
</p>
● Routes での権限、ロール判定
app/Http/Kernel.php (63行目あたり)
protected $routeMiddleware = [
// ...
'role' => \Spatie\Permission\Middlewares\RoleMiddleware::class,
'permission' => \Spatie\Permission\Middlewares\PermissionMiddleware::class,
];
Routesには以下のように記述します
App/routes/web.php
// 誰でもアクセス可能
Route::resource('users', 'UserController');
↓
// 「ログイン」している時のみアクセス可能
Route::group(['middleware' => ['auth']], function() {
Route::resource('users', 'UserController');
});
↓
// 「ログイン」かつ「admin_permissionを持つ」時のみアクセス可能
Route::group(['middleware' => ['auth']], function() {
Route::group(['middleware' => ['permission:admin_permission']], function () {
Route::resource('users', 'UserController');
});
});
です。
● 権限(permissions)やロール(roles)の一覧を取得する
モデルを作成します。
/app/Permission.php
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Permission extends Model
{
protected $table = 'permissions';
protected $guarded = ['id', 'created_at', 'updated_at'];
}
// 全ての permissionsの取得
\App\Permission::get();
● There is no permission named xxxxx_permission for guard web. というエラーが出る場合の対処法
こちらのエラーですが、DBの permissions を変更した後、キャッシュが残っている場合に表示されます。
次のコマンドでLaravelのキャッシュをクリアしましょう。
php artisan cache:clear