Laravelで、入力フォームのバリデーション用に、FormRequestクラスを継承するEmployeeRequestクラスを作成しました。
EmployeeRequestクラスは、コントローラのstoreメソッド(追加処理)とupdateメソッド(更新処理)に DI して使います。
ですが、store
とupdate
では、バリデーションルールにちょっとだけ違いがありました。
ルールの違いをコントローラ側で意識したくありません。
EmployeeController@store
/**
* 追加処理(新規入力フォームの登録ボタンで呼び出される)
*/
public function store(EmployeeRequest $request) {
Employee::create($request->all());
return redirect()->route('employee');
}
EmployeeController@update
/**
* 更新処理(編集フォームの更新ボタンで呼び出される)
*/
public function update(EmployeeRequest $request, $id) {
Employee::find($id)->update($request->all());
return redirect()->route('employee');
}
このような場合、Laravelでどう書くのがセオリーなのでしょうか。自分はAfterフックのwithValidator
メソッドで対処しました。
Route::currentRouteName
が現在のルート名を返すので、これを評価すれば、storeメソッド(追加処理)かどうか判断できます。
EmployeeRequest.php
class EmployeeRequest extends FormRequest
{
// 標準ルール
public function rules() {
return [
'name' => 'bail|required|string|max:191',
// email はシステム内でuniqueとする
'email' => ['required', 'email', 'max:191', Rule::unique('employees')->ignore($this->id)],
// employee_id(従業員番号)はその会社内でuniqueとする
'employee_id' => ['required', 'string', 'max:30', Rule::unique('employees')->ignore($this->id)->where('company_id', Auth::user()->company_id)],
// 以降、省略
:
:
];
}
// 現在のルートが employee.store なら password をバリデーション
public function withValidator(Validator $validator) {
$validator->sometimes('password', 'required|string|between:8,20|confirmed', function() {
return \Route::currentRouteName() == 'employee.store';
});
}
}
web.php
Route::get('/employee/create', [EmployeeController::class, 'create'])->name('employee.create');
Route::post('/employee/store', [EmployeeController::class, 'store'])->name('employee.store');
モデルにバリデーションルールを定義し、FormRequestクラスで切り替えるとか、もっと素直で良いやり方があるかもしれません。