標準認証で使われているミドルウェアguestとwebはどこで指定されている？ - Laravelコードリーティング

# 趣旨 & 前置き

Laravel5.6のコードを読んでいきます。
Laravel標準の認証では、認証済み（ログイン済み）の状態でログインページにアクセスすると、ログイン後のトップページにリダイレクトします。

認証について解説するページは多いですが、このあたりの動きを解説しているページってみたことないので、書いてみようと思いました。

確認する環境はHomesteadでLaravelをインストールし、

```
php artisan make:auth
php artisan migrate
```

だけやった状態だと思います（うろ覚え）

# Let's コードリーディング！

ログインしている場合にログイン後のトップページにリダイレクトする処理はApp\Http\Middleware\RedirectIfAuthenticatedクラスに書かれています。

## RedirectIfAuthenticatedクラス

```php

public function handle($request, Closure $next, $guard = null)
{   
    if (Auth::guard($guard)->check()) {
        return redirect('/home');
    }   

    return $next($request);
}

```

認証しているかチェックして、認証していたら/homeにリダイレクトしています。
これが「認証済み（ログイン済み）の状態でログインページにアクセスすると、ログイン後のトップページにリダイレクトする」処理です。（guardなどの細かい説明についてはここではしません。）

さて、問題はこのRedirectIfAuthenticatedクラスがどのように呼び出されているかです。
ネームスペースでわかる通り、RedirectIfAuthenticatedクラスはミドルウェアです。どこかでこのミドルウェアを指定する箇所があるはずです。探してみましょう。

## Kernelクラス

開発中のアプリケーションで利用されるミドルウェアはApp\Http\Kernelクラスに記述します。
該当部分を抜粋します。

```php

protected $routeMiddleware = [
    'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
];

```

RedirectIfAuthenticatedクラスはguestという名前で登録されているようです。

## ルーティングの確認

guestという名前のミドルウェアがどのルーティングで利用されているのかを確認するために、ルーティングを確認してみましょう。

まず、routes/web.phpをみてみます。

```php
Route::get('/', function () {
    return view('welcome');
});

Auth::routes();

Route::get('/home', 'HomeController@index')->name('home');
```

これだとなんだかよくわかりませんね。
なので以下のコマンドでルーティングの確認をしてみましょう。

```
php artisan route:list
```

ルーティングの一覧が表示されるかと思います。
今回関連する部分を抜粋します。

| Domain | Method   | URI                    | Name             | Action                                                                 | Middleware   |
|:---|:---|:---|:---|:---|:---|
|        | GET/HEAD | home                   | home             | App\Http\Controllers\HomeController@index                              | web          |
|        | GET/HEAD | login                  | login            | App\Http\Controllers\Auth\LoginController@showLoginForm                | web,guest    |
|        | POST     | login                  |                  | App\Http\Controllers\Auth\LoginController@login                        | web,guest    |
|        | POST     | logout                 | logout           | App\Http\Controllers\Auth\LoginController@logout                       | web          |
|        | POST     | password/email         | password.email   | App\Http\Controllers\Auth\ForgotPasswordController@sendResetLinkEmail  | web,guest    |
|        | GET/HEAD | password/reset         | password.request | App\Http\Controllers\Auth\ForgotPasswordController@showLinkRequestForm | web,guest    |
|        | POST     | password/reset         |                  | App\Http\Controllers\Auth\ResetPasswordController@reset                | web,guest    |
|        | GET/HEAD | password/reset/{token} | password.reset   | App\Http\Controllers\Auth\ResetPasswordController@showResetForm        | web,guest    |
|        | GET/HEAD | register               | register         | App\Http\Controllers\Auth\RegisterController@showRegistrationForm      | web,guest    |
|        | POST     | register               |                  | App\Http\Controllers\Auth\RegisterController@register                  | web,guest    |

guestミドルウェアが利用されていますね。ミドルウェアが利用されているミドルウェアの指定はControllerのコンストラクタでも可能ですから、LoginControllerクラス / RegisterControllerクラス/ResetPasswordControllerクラス/ForgotPasswordControllerクラスを覗いてみましょう。

## LoginControllerクラス / RegisterControllerクラス / ResetPasswordControllerクラス / ForgotPasswordControllerクラス

App\Http\Controllers\Auth\LoginControllerクラスのコンストラクタをみてましょう。

```php

public function __construct()
{   
    $this->middleware('guest')->except('logout');
}

```

App\Http\Controllers\Auth\RegisterControllerクラス、App\Http\Controllers\Auth\ResetPasswordControllerクラス、App\Http\Controllers\Auth\ForgotPasswordControllerクラスのコンストラクタも同じように見てみます。

```php

public function __construct()
{   
    $this->middleware('guest');
} 

```

ありました。guestミドルウェア = RedirectIfAuthenticatedクラスを指定しています。これで「認証済み（ログイン済み）の状態でログインページにアクセスすると、ログイン後のトップページにリダイレクトする」仕組みが理解できたと思います。

## webミドルウェア

ルーティングの一覧のところにwebというミドルウェアグループも指定されていましたが、これについてもどこで指定されているのか確認してみましょう。

webミドルウェアグループはKernelクラスに以下のように記述されています。

```php

protected $middlewareGroups = [ 
    'web' => [
        \App\Http\Middleware\EncryptCookies::class,
        \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
        \Illuminate\Session\Middleware\StartSession::class,
        \Illuminate\View\Middleware\ShareErrorsFromSession::class,
        \App\Http\Middleware\VerifyCsrfToken::class,
        \Illuminate\Routing\Middleware\SubstituteBindings::class,
    ]
];

```

webミドルウェアグループがどこで指定されているのかは、実はドキュメントにちゃんと書いてあります。[このへん](https://readouble.com/laravel/5.6/ja/middleware.html#middleware-groups)です。（突然の大雑把）

> Tip!! RouteServiceProviderにより、routes/web.phpファイルでは、webミドルウェアグループが自動的に適用されます。

そう、App\Providers\RouteServiceProviderクラスで指定されているのです。

## RouteServiceProviderクラス

例によってRouteServiceProviderクラスの該当箇所を抜粋してみます。

```php

public function map()
{
    $this->mapApiRoutes();
    $this->mapWebRoutes();
}   

protected function mapWebRoutes()
{   
    Route::middleware('web')
         ->namespace($this->namespace)
         ->group(base_path('routes/web.php'));
} 

```

ここでwebミドルウェアグループを指定していますね！
このコードが示す通り、routes/web.phpに記述されたルーティングは基本的にwebミドルウェアが利用されるようです。

# 終わりに

間違ってたら指摘オナシャス。