Laravelの認証処理の中の処理など「Closure $next, ...$guards
」という記述が出てくることがあります。
この「Closure $next, …$guards」とは何なのか?「$next」や「…$guards」「guards」とは何か、それぞれどのような処理をしているのかについてまとめています。
結論:Closure $next, …$guardsとは何か?
結論からいうと、Closure $next
はClosureクラスで無名関数$nextを作成。
...$guards
の...
は渡された複数のデータ(数に指定なし)を変数$guardsとして渡すという意味。
登場する場所
Closure $next, ...$guards
は認証処理用のミドルウェアRedirectIfAuthenticated.phpに記述されている。
App > Http > Middleware > RedirectIfAuthenticated.php
<?php
namespace App\Http\Middleware;
use App\Providers\RouteServiceProvider;
use Closure;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
class RedirectIfAuthenticated
{
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @param string|null ...$guards
* @return mixed
*/
public function handle(Request $request, Closure $next, ...$guards)
{
$guards = empty($guards) ? [null] : $guards;
foreach ($guards as $guard) {
if (Auth::guard($guard)->check()) {
return redirect(RouteServiceProvider::HOME);
}
}
return $next($request);
}
}
もう少し細かく見ると、
(1)ルーティングでmiddlewareのguestが指定される。
Route::get('/login', [AuthenticatedSessionController::class, 'create'])
->middleware('guest')
->name('login');
(2) ミドルウェアのguestはKernel.phpの中でグローバル登録されている。
protected $routeMiddleware = [
'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
];
(3) ミドルウェアguestで\App\Http\Middleware\RedirectIfAuthenticatedが実行される。
このRedirectIfAuthenticatedの中の処理となる。
$nextとは何か?
・Closure $next
Clouserクラス
無名関数を作るクラス。
関数の引数の中でClosure 変数名
とすることで、無名関数のインスタンスを指定した変数名で作成する。(依存注入)
$next
無名関数のインスタンスが入った変数。middlewareの処理でのみ登場する。
処理結果をコントローラに渡す。
public function handle(Request $request, Closure $next, ...$guards)
{
$guards = empty($guards) ? [null] : $guards;
foreach ($guards as $guard) {
if (Auth::guard($guard)->check()) {
return redirect(RouteServiceProvider::HOME);
}
}
return $next($request);
}
…$guardsとは何か?
こちらもhandle関数の引数で渡されているデータ。
...
は可変長引数。任意の数だけ引数を渡すことができる。
通常は一つの引数に対して一つのデータが渡された順に入っていく。可変長引数にすると、入力したデータをすべて渡すことができる。(引数の数が合わない!というエラーが出ない)
変数$guards
はphp doc(説明文)を見ると、文字列か空とのこと。
* @param string|null ...$guards
guardsとは何か?
Laravelのguard(ガード)とは、各リクエスト毎にどのようにユーザーを認証するかを定義したもの。
config > auth.php の中で定義されている。
'guards' => [
'web' => [
'driver' => 'session',
'provider' => 'users',
],
'api' => [
'driver' => 'token',
'provider' => 'users',
'hash' => false,
],
],
通常のブラウザ経由での認証の場合はweb
を参照する。
・'driver' => 'session'
認証状況のデータの受け渡しはセッションを使用。(APIの場合はセッション情報ではなくトークンを使う)
・'provider' => 'users',
認証状況の照合にはusersテーブル(userモデル)を使用する。
handle関数の処理内容
変数guards
$guards = empty($guards) ? [null] : $guards;
これは三項演算子による書き方。
条件式 ? 式1 : 式2
。
//$guardsが空の場合(次のforeach処理でエラーが出ないようにする)
$guards=[null]
//$guards`が空でない
$guards = $guards
ここでは$guardsはconfig > auth.php の中で定義されている内容が入る。(nullではない)
'guards' => [
'web' => [
'driver' => 'session',
'provider' => 'users',
],
'api' => [
'driver' => 'token',
'provider' => 'users',
'hash' => false,
],
],
認証状況の判断
・Auth::guard('ガード名')
Authファサードのguardメソッドでガード名を指定することで、指定したガードを呼び出す。
ここでは、webとapiが順番に呼び出される
・checkメソッド
ユーザーが既にログインしているかを調べる。
foreach ($guards as $guard) {
if (Auth::guard($guard)->check()) {
return redirect(RouteServiceProvider::HOME);
}
}
ユーザーが既にログインしている場合は、RouteServiceProvider
クラスの定数HOMEで指定したページにリダイレクトする。
Providers > RouteServiceProvider.php に記述がある。
class RouteServiceProvider extends ServiceProvider
{
public const HOME = '/dashboard';
つまり、既にログイン済み(認証済み)であれば/dashboardページが開く。
ログイン済みでない場合
無名関数のnextで、次のミドルウェアにHTTPリクエストが渡される。
return $next($request);