Laravel5.7: 1回限りのメッセージを表示する

「記事を更新しました。」「ログインしました。」などの1回限りのメッセージを表示します。

![001.png](https://qiita-image-store.s3.amazonaws.com/0/27816/5c08e99b-0e0c-e024-3c1d-9431975d113f.png)


# 親記事
[Laravel 5.7で基本的なCRUDを作る - Qiita](https://qiita.com/sutara79/items/ef30fcdfb7afcb2188ea)


# メッセージを表示する場所
:link: readouble.com: [フラッシュデータを保存するリダイレクト](https://readouble.com/laravel/5.7/ja/responses.html#redirecting-with-flashed-session-data)

フラッシュメッセージを表示する場所をレイアウト内に設けます。
一時的な保存に使うセッション名は`my_status`で統一します。

```diff:resources/views/layouts/my.blade.php
         </nav>
 
+        {{-- フラッシュ・メッセージ --}}
+        @if (session('my_status'))
+            <div class="container mt-2">
+                <div class="alert alert-success">
+                    {{ session('my_status') }}
+                </div>
+            </div>
+        @endif
+
         <main class="py-4">
             @yield('content')
         </main>
```


# postsとusers関連のメッセージ
`with`メソッドで簡単にビューへメッセージを渡すことができます。

```diff:app/Http/Controllers/PostController.php
     public function store(StorePost $request)
     {
-        return redirect('posts/' . $post->id);
+        return redirect('posts/' . $post->id)->with('my_status', __('Posted new article.'));
(中略)
     public function update(StorePost $request, Post $post)
     {
-        return redirect('posts/'.$post->id);
+        return redirect('posts/' . $post->id)->with('my_status', __('Updated an article.'));
(中略)
     public function destroy(Post $post)
     {
-        return redirect('posts');
+        return redirect('posts')->with('my_status', __('Deleted an article.'));
```

```diff:app/Http/Controllers/UserController.php
     public function store(StoreUser $request)
     {
-        return redirect('users/' . $user->id);
+        return redirect('users/' . $user->id)->with('my_status', __('Created new user.'));
(中略)
     public function update(Request $request, User $user)
     {
-        return redirect('users/' . $user->id);
+        return redirect('users/' . $user->id)->with('my_status', __('Updated a user.'));
(中略)
     public function destroy(User $user)
     {
-        return redirect('users');
+        return redirect('users')->with('my_status', __('Deleted a user.'));
     }
```


# 認証関連のメッセージ
デフォルトの認証では、パスワード再設定でのメール送信完了と、メール確認での再送信完了については、すでにフラッシュメッセージが用意されています。
しかし、ログイン、ログアウト、ユーザー登録、メール確認の完了については用意されていないので自作する必要があります。
また、パスワード再設定の完了は少し修正が必要です。
:link: Laracastsの質問: [Laravel 5.2 Auth Flash Message](https://laracasts.com/discuss/channels/laravel/laravel-52-auth-flash-message)

## ログイン
下記のトレイトの`authenticated`メソッドをLoginControllerで上書きします。
:link: [Illuminate\Foundation\Auth\AuthenticatesUsers](https://github.com/laravel/framework/blob/5.7/src/Illuminate/Foundation/Auth/AuthenticatesUsers.php#L117)

```php:app/Http/Controllers/Auth/LoginController.php
// 忘れずにインポートすること!!
use Illuminate\Http\Request;

    (中略)

    /**
     * ログイン後の処理
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  mixed  $user
     * @return \Illuminate\Http\Response
     */
    protected function authenticated(Request $request, $user)
    {
        // ログインしたら、ユーザー自身のプロフィールページへ移動
        return redirect('users/' . $user->id)->with('my_status', __('You logged in.'));
    }
```

## ログアウト
まず、Laravel5.7でのログアウトのルートを確認します。
下記のコマンドで、`App\Http\Controllers\Auth\LoginController@logout`だと分かりました。
ログインと同じく、Loginコントローラに`logout`メソッドを定義するようです。

```text:PowerShell
> php artisan route:list
```

下記のトレイトの`logout`メソッドをLoginControllerで上書きします。
:link: [Illuminate\Foundation\Auth\AuthenticatesUsers](https://github.com/laravel/framework/blob/5.7/src/Illuminate/Foundation/Auth/AuthenticatesUsers.php#L153)

```php:app/Http/Controllers/Auth/LoginController.php
    /**
     * ユーザーをログアウトさせる
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Illuminate\Http\Response
     */
    public function logout(Request $request)
    {
        $this->guard()->logout();
        $request->session()->invalidate();

        // ログアウトしたら、トップページへ移動
        return $this->loggedOut($request) ?: redirect('/')->with('my_status', __('You logged out.'));
    }
```

## ユーザー登録
下記のトレイトの`registered`メソッドをRegisterControllerで上書きします。
:link: [Illuminate\Foundation\Auth\RegistersUsers](https://github.com/laravel/framework/blob/5.7/src/Illuminate/Foundation/Auth/RegistersUsers.php#L58)

```php:app/Http/Controllers/Auth/RegisterController.php
// 忘れずにインポートすること!!
use Illuminate\Http\Request;

    (中略)

    /**
     * ユーザー登録後の処理
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  mixed  $user
     * @return \Illuminate\Http\Response
     */
    protected function registered(Request $request, $user)
    {
        // 登録したら、そのユーザーのプロフィール・ページへ移動
        return redirect('users/' . $user->id)->with('my_status',
            __('Registration have not yet completed.') .
            __('Check your email for a verification link.')
        );
    }
```

## メール確認の完了
下記のトレイトの`verify`メソッドをVerificationControllerで上書きします。
:link: [Illuminate\Foundation\Auth\VerifiesEmails](https://github.com/laravel/framework/blob/5.7/src/Illuminate/Foundation/Auth/VerifiesEmails.php)

```php:app/Http/Controllers/Auth/VerificationController.php
// 忘れずにインポートすること
use Illuminate\Auth\Events\Verified;

    (中略)

    /**
     * ユーザーのメールアドレスを確認完了とする
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Illuminate\Http\Response
     */
    public function verify(Request $request)
    {
        if ($request->route('id') == $request->user()->getKey() &&
            $request->user()->markEmailAsVerified()) {
            event(new Verified($request->user()));
        }
        return redirect($this->redirectPath())->with('my_status', __('Registration completed.'));
    }
```

## パスワード再設定の完了
再設定用のメール送信の完了と同じく、再設定の手続きすべてが完了してリダイレクトする際にも、フラッシュメッセージを表示するようにあらかじめ設定されています。
しかしそのセッション名が`status`なので、これを`my_status`に変更しなければなりません。

下記のトレイトの`sendResetResponse`メソッドをResetPasswordControllerで上書きします。
:link: [Illuminate\Foundation\Auth\ResetsPasswords](https://github.com/laravel/framework/blob/5.7/src/Illuminate/Foundation/Auth/ResetsPasswords.php#L123)

```php:app/Http/Controllers/Auth/ResetPasswordController.php
// 忘れずにインポートすること
use Illuminate\Http\Request;

    (中略)

    /**
     * パスワード再設定が完了した場合の処理
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  string  $response
     * @return \Illuminate\Http\RedirectResponse|\Illuminate\Http\JsonResponse
     */
    protected function sendResetResponse(Request $request, $response)
    {
        // リダイレクト先でフラッシュメッセージを表示する
        return redirect($this->redirectPath())
                            ->with('my_status', trans($response));
    }
```