【Laravel】パスワードリセットに生年月日チェックを追加した

えび

Laravelパスワード再発行画面
メールアドレス以外の他カラムを追加したい時のメモ

今回は生年月日を追加する

=== Viewに生年月日セレクトボックスを追加するところは省略 ===

ForgetPasswordControllerを改修

  • Auth/ForgetPasswordController.php
<?php

namespace App\Http\Controllers\Auth;

use App\Http\Controllers\Controller;
use Illuminate\Foundation\Auth\SendsPasswordResetEmails;

class ForgotPasswordController extends Controller
{  
    use SendsPasswordResetEmails;

    protected function validateEmail(Request $request)
    {
        $request->validate([
            'email' => 'required|email',
            'birth_y' => 'required',
            'birth_m' => 'required',
            'birth_d' => 'required',
            ]
        );
    }

    protected function credentials(Request $request)
    {
        return $request->only(['email', 'birth_y', 'birth_m', 'birth_d']);
    }

    protected function sendResetLinkFailedResponse(Request $request, $response)
    {
        return back()
            ->withInput($request->only(['email', 'birth_y', 'birth_m', 'birth_d']))
            ->withErrors(['email' => trans($response)]);
    }
}
変更内容

オーバーライドするために下記メソッドを追記

  • validateEmail()
  • credentials()
  • sendResetLinkFailedResponse()

CustomAuthServiceProviderを作成

php artisan make:provider CustomAuthServiceProvider
  • app/Providers/CustomAuthServiceProvider.php
<?php

namespace App\Providers;

use Illuminate\Contracts\Support\Arrayable;
use Illuminate\Support\Str;

class CustomAuthServiceProvider extends \Illuminate\Auth\EloquentUserProvider
{
    public function retrieveByCredentials(array $credentials)
    {
        if (empty($credentials) ||
            (count($credentials) === 1 &&
                Str::contains($this->firstCredentialKey($credentials), 'password'))) {
            return;
        }

        // First we will add each credential element to the query as a where clause.
        // Then we can execute the query and, if we found a user, return it in a
        // Eloquent User "model" that will be utilized by the Guard instances.
        $query = $this->newModelQuery();

        foreach ($credentials as $key => $value) {
            if (Str::contains($key, 'password')) {
                continue;
            }

            /**
             * 生年月日判定追加
             */
            if ($key === 'birth_y') {
                $query->whereYear('birth', $value);
                continue;
            }
            if ($key === 'birth_m') {
                $query->whereMonth('birth', $value);
                continue;
            }
            if ($key === 'birth_d') {
                $query->whereDay('birth', $value);
                continue;
            }
            
            if (is_array($value) || $value instanceof Arrayable) {
                $query->whereIn($key, $value);
            } else {
                $query->where($key, $value);
            }
        }

        return $query->first();
    }
}
何をしてるか

EloquentUserProvider::retrieveByCredentials()
DBからユーザー情報を探すので、ここに追加したいカラム条件を実装する

ただし直接編集はできないので、
今回作成するCustomAuthServiceProviderクラスで
EloquentUserProviderクラスを継承 & retrieveByCredentials()メソッドをオーバーライドしてる

プロバイダへ登録する

  • app/Providers/AuthServiceProvider.php
 public function boot(Gate $gate)
    {
        $this->registerPolicies();


        if (!app()->runningInConsole()) {
            $this->definePermissions($gate);
        }
 
        // カスタム用サービスプロバイダを登録
        Auth::provider('custom_auth', function($app, array $config) {
            return new CustomAuthServiceProvider($this->app['hash'], $config['model']);
        });
    }

custom_authをドライバとして使用させる

  • config/auth.php
'providers' => [
        'users' => [
            'driver' => 'custom_auth', // ⭐️ ここを変更
            'model' => App\User::class,
        ],
        // 'users' => [
        //     'driver' => 'database',
        //     'table' => 'users',
        // ],
    ],

バリデーションメッセージも変更しとく

  • resources/en/passwords.php
<?php

return [

    /*
    |--------------------------------------------------------------------------
    | Password Reset Language Lines
    |--------------------------------------------------------------------------
    |
    | The following language lines are the default lines which match reasons
    | that are given by the password broker for a password update attempt
    | has failed, such as for an invalid token or invalid new password.
    |
    */

    'password' => 'Passwords must be at least eight characters and match the confirmation.',
    'reset' => 'Your password has been reset!',
    'sent' => 'We have e-mailed your password reset link!',
    'token' => 'This password reset token is invalid.',
    'user' => "We can't find a user.", // 変更

];