【Laravel】ユーザーパスワードリセット機能を実装する

今回はLaravelでパスワードをユーザーのパスワードをリセットする機能を実装します。

# 開発環境

PHP 7.3.9
MAMP 5.7
Mysql 5.7.26
Laravel 6.20.7
Composer 2.0.8

# ユーザー認証機能の実装及びDB接続

まずは認証機能を作成しておきましょう。

```
$ composer require laravel/ui "1.x" --dev
$ php artisan ui bootstrap --auth
$ npm install && npm run dev
```

次にDB接続。
.envファイルに環境変数を設定して、

```
$ php artisan migrate
```

もし上手く行かない方はこちらを参考にしてください。
[【MAMP】laravelのMySQL接続エラー([1045] Access denied for user)](https://qiita.com/mineaki27th/items/5effcc2605fe90ff6997)



# Laravelからメールを送信できるように設定

まずはLaravelでメールを送信できるようにしていないといけません。
今回はGmailのSMTPサーバーを用いて実装していきます。

## Googleアカウントを準備

はじめにGoogleアカウントを用意してください。
用意したGoogleアカウントのGmailアドレスからパスワード再設定のメールを送信することになります。

## 安全性の低いアプリの許可を有効に設定

用意したGoogleアカウントの設定を変更します。
下記のリンクを押して使用する予定のGoogleアカウントに切り替えましょう。
その後、「安全性の低いアプリの許可」を**有効**にします。
[安全性の低いアプリのアクセス](https://myaccount.google.com/lesssecureapps)


## .envで環境変数を追加する

```:.env
MAIL_DRIVER=smtp
MAIL_HOST=smtp.gmail.com
MAIL_PORT=587
MAIL_USERNAME=<Gmailアドレス>
MAIL_PASSWORD=<Gmailパスワード>
MAIL_ENCRYPTION=tls
MAIL_FROM_ADDRESS=<Gmailアドレス>
MAIL_FROM_NAME=<任意の名前>
```

MAIL_USERNAMEのところはGoogleアカウントのユーザーネームを入力してもメールが送信できなかったのでそのままメールアドレス入力したら送信できました。

## 送信できるかテストをする

ターミナルで下記のコマンド実行しましょう。
**null**が帰って来れば成功です。

```
$ php artisan tinker
Psy Shell v0.10.8 (PHP 7.3.9 — cli) by Justin Hileman
>>> Mail::raw('test mail', function($message) {$message->to('<送信先アドレス>')->subject('Test');});
=> null
```

# 通知クラスを用いて再設定メールのテンプレートを作成する

`app/Notifications/UserResetPassword.php`を生成します。

```
$ php artisan make:notification UserResetPassword
```

生成した`app/Notifications/UserResetPassword.php`を編集。

```php:app/Notifications/UserResetPassword.php
<?php

namespace App\Notifications;

use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Notifications\Messages\MailMessage;
use Illuminate\Notifications\Notification;
use Illuminate\Auth\Notifications\ResetPassword;

class UserResetPassword extends Notification
{
    use Queueable;

    /**
    * The password reset token.
    * 
    * @var string
    */
    public $token;

    /**
     * Create a new notification instance.
     *
     * @param string $token
     * @return void
     */
    public function __construct($token)
    {
        $this->token = $token;
    }

    /**
     * Get the notification's delivery channels.
     *
     * @param  mixed  $notifiable
     * @return array
     */
    public function via($notifiable)
    {
        return ['mail'];
    }

    /**
     * Get the mail representation of the notification.
     *
     * @param  mixed  $notifiable
     * @return \Illuminate\Notifications\Messages\MailMessage
     */
    public function toMail($notifiable)
    {
        return (new MailMessage)
            ->subject('パスワード再設定')
            ->greeting('平素よりアプリをご利用いただきありがとうございます')
            ->line('下のボタンをクリックしてパスワードを再設定してください。')
            ->action(__('パスワードを再設定'), url(config('app.url').route('password.reset', $this->token, false)))
            ->line('もしこのメールに心当たりがない場合は、そのまま削除してください。');
    }

    /**
     * Get the array representation of the notification.
     *
     * @param  mixed  $notifiable
     * @return array
     */
    public function toArray($notifiable)
    {
        return [
            //
        ];
    }
}

```

app/User.phpを編集する

```php:app/User.php
<?php

namespace App;

use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use App\Notifications\UserResetPassword;

class User extends Authenticatable
{
    (略)

    /**
     * パスワードリセット通知の送信
     *
     * @param  string  $token
     * @return void
     */
    public function sendPasswordResetNotification($token)
    {
        $this->notify(new UserResetPassword($token));
    }
}
```

最後に送られてきたメール内のパスワードの再設定用リンクのパスを修正。

```php:app/Notifications/UserResetPassword.php
->action(__('パスワードを再設定'), url(config('app.url').route('password.reset', $this->token, false)))
```

`config('app.url')`であり、
デフォルトの設定だと、

```:.env
APP_URL=http://localhost
```

となっているがこのままだとポート番号が記述されていないので再設定の画面が表示されない。

そのため自身のポート番号に合わせる必要がある

![2ec76b7ea7421390ad9cdb884e74cae7.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/474463/7ae95208-c30f-6608-3c19-ee439a4e96a2.png)

今回は8000番ポートなので

```:.env
APP_URL=http://localhost:8000
```

とすればメール内の再設定画面へのリンクも問題なく遷移できるはずです。

![241cb0f2624df39c71997cd2f444472f.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/474463/b101e02e-35e9-184b-c8a2-72ae6fc914f8.png)