管理者・編集者・閲覧者のように各ユーザーに権限を持たせて、その権限に応じて表示させる内容を変える方法です。この記事では、Lavavel6のGate(ゲート)を使って実装します。
Gate(ゲート)とは? Gateとは、特定のユーザーのみにあるアクションを許可する機能です。「管理者のみ」という条件を定義しておけば、管理者のみ記事削除ボタンを表示させたりできます。
ユーザーテーブルに権限カラムを追加する
ユーザー情報を保存するusersテーブルに権限識別用のカラムを追加します。今回の例ではroleという名前で追加しています。
// app/database/migrations/20XX_XX_XX_000000_create_users_table.php:14行目付近
public function up()
{
Schema::create('users', function (Blueprint $table) {
$table->bigIncrements('id');
$table->string('name');
$table->string('email')->unique();
$table->timestamp('email_verified_at')->nullable();
$table->string('password');
$table->string('role'); // ここを追加
$table->rememberToken();
$table->timestamps();
});
}
カラムを追加したら、マイグレーションします。
ユーザー認証機能を構築する
ユーザー認証機能を構築することによって、アプリケーション上でユーザー登録とログイン・ログアウトができるようになります。Laravel6にはユーザー認証機能が用意されていないので、パッケージを使って構築していきます。
下記コマンドを実行し、composerでlaravel/uiパッケージをインストールします。laravel/uiパッケージは、フロントエンドのフレームワークを組み込むときのベースになる機能を提供してくれるものです。これを使って、ユーザー認証機能のフロントエンド部分を生成します。Laravel6の場合はバージョン1にしか対応していないので、バージョン1をインストールします。
$ composer require laravel/ui "^1.0" --dev
次に、下記artisanコマンドでユーザー認証機能を追加します。
$ php artisan ui vue --auth
ここまででLavavelにユーザー認証機能を追加できましたが、まだフロントエンド側が残っています。下記コマンドで、npmをインストールしてビルドします。Node.jsが必要なので、PCにインストールしていない場合は別途インストールします。
$ npm install
$ npm run dev
これでフロントページ右上に「LOGIN」と「REGISTER」が表示されて、ユーザー認証機能が使えるようになります。
ユーザー登録して権限を管理者にする
先ほど作ったユーザー認証機能を使って、新しくユーザーを登録します。phpMyAdminを使ってusersテーブルを開き、登録したユーザーの権限(roleカラム)を変更します。今回は管理者という意味で「administrator」という文字列にします。
roleが変更できればいいので、必ずしもphpMyAdminを使う必要はありません。
Gateを定義する
今回は「管理者のみ」という条件をGateで定義します。App\Providers内にあるAuthServiceProvider.phpというファイルのboot()内にGateファサードを使って定義します。
// App\Providers\AuthServiceProvider.php:24行目付近
public function boot()
{
$this->registerPolicies();
Gate::define('isAdmin', function($user){
return $user->role === 'administrator';
});
}
上記コードの7~9行目で「isAdmin」という名前でGateを定義しているので、ここの部分を追記します。Gateは第1引数にユーザーインスタンスを受け取るので、そのユーザーインスタンスのroleがadministratorと等しいかをreturnで返しています。
Bladeディレクティブ@canでGateを使う
先ほど定義したGateはBladeディレクティブで使用できます。管理者ユーザー(roleがasministrator)のみ削除ボタンを表示させたい場合は、下記のようになります。
// blade
@can('isAdmin')
<button>削除する</button>
@else
<p>管理者しか削除できません</p>
@endcan
コントローラーの処理でGateを使う
コントローラーの処理でGateを使用することもできます。管理者ユーザーのみ実行できる処理を書く場合は、下記のようになります。
use Gate;
class PostController extends Controller
{
public function index()
{
Gate::authorize('isAdmin');
// 管理者ユーザーのみ以下処理が実行される
$posts = Post::all();
return view('posts.index', compact('posts'));
}
}
まず、1行目のようにuseでGateを読み込みます。7行目で管理者ユーザーの認証を行っています。管理者ユーザーでない場合は403ページに飛ばされて、それ以降の処理は実行されません。
条件を追加する
「管理者、あるいは記事を投稿したユーザーのみ」という条件に変更してみます。投稿記事のテーブルには、投稿者ID(user_idカラム)がある想定です。
// App\Providers\AuthServiceProvider.php:24行目付近
public function boot()
{
$this->registerPolicies();
Gate::define('isAdmin', function($user, $post){
return $user->role === 'administrator' || $user->id === $post->user_id;
});
}
7行目に$postという引数を追加しました。のちにbladeディレクティブの第2引数に記事のコレクションを指定します。その値がここに入ってきます。
8行目で、「ログインしているユーザーのIDと記事のuser_idが等しいか」という条件を追加しています。
// blade
@foreach ($posts as $post)
@can('isAdmin', $post)
<button>削除する</button>
@else
<p>管理者か、この記事の投稿者しか削除できません</p>
@endcan
@endforeach
4行目のように、第2引数に記事のコレクションを指定することで、先ほど定義したGate内で判定に使用することができます。