Laravelで重複チェック(unique)を行う際に、IDが同じ場合は重複のチェックを除外したい場合の方法です。
よくあるパターンだと、メールアドレスをユーザーテーブルに保存していて、ログインにアドレスを使っている場合、ユーザー情報を更新する際に、重複チェックに引っかかってしまうパターンが多いかなと思います。
今回は、FormRequestを使っているので、FormRequestに記述する方法を記載します。
FormRequestの記述
Usersテーブルに対してリクエストを行い、重複チェックを行う想定で実装していきます。
artisanコマンドでUserRequestを作成します。
php artisan make:request UserRequest
app/Http/Requests/UserRequest.php に UserRequest.php が作成されるので、UserRequest.phpのrulesメソッドに下記を記述します。
use Illuminate\Validation\Rule;
class UserRequest extends FormRequest
{
/**
* Get the validation rules that apply to the request.
*
* @return array
*/
public function rules()
{
return [
'email' => ['required', Rule::unique('users')->ignore($this->id)],
];
}
}
ignoreメソッドについて
Rule::uniqueのignoreの内容は、下記のようになります。
Rule::unique({テーブル名またはModel})->ignore({チェックする値}, {カラム名})
テーブルのしては、Modelを指定することも可能なので、以下のような記述も可能です。
return [
'email' => ['required', Rule::unique('App\User')->ignore($this->id)],
];
Modelを指定した方が、汎用性が高いかもしれませんね。
igonoreメソッドの第二引数は、チェックするカラム名を指定することができます。
例えば、プライマリキーがidではなくserialだった場合、
return [
'email' => ['required', Rule::unique('users')->ignore($this->id, 'serial')],
];
で、serialカラムでIDの重複チェックを行います。
また、where句など検索条件を指定することも可能です。
deleted_atがnullのもので重複チェックを行う場合、
return [
'email' => ['required', Rule::unique('users')->ignore($this->id)->whereNull('deleted_at')],
];
のような条件を指定することが可能です。
Controllerでの呼び出し
Controller側でUserRequestを指定します。今回はupdateメソッドに追記していきます。
use App\Http\Requests\UserUpdateRequest;
class UserController extends Controller
{
/**
* Update the specified resource in storage.
*
* @param UserRequest $request
* @param int $id
* @return JsonResource
*/
public function update(UserRequest $request, int $id)
{
}
}
これで、UserControllerに到達する前に、UserRequestでバリデーション処理が実行され、メールアドレスの重複チェックが行われます。
ユーザー情報のIDの重複チェックについて
今回は、ユーザーのメールアドレスの重複チェックを例に上げましたが、今回の場合だとマイページなどでユーザー情報の更新を行う場合が想定されると思います。
その場合は、すでにユーザーがログイン済みなので、requestのidを取得するより、Auth::id()で取得した方が良いかもしれません
return [
'email' => ['required', Rule::unique('users')->ignore(Auth::id())],
];