メモ
Controller
validateメソッドの - 第一引数がRule - 第二引数がエラーメッセージ - 第三引数がAttribute名
<?php use App\Rules\UserPassword; class PasswordController extends Controller { /** * Update the user's password. */ public function update(Request $request): RedirectResponse { $validated = $request->validate( [ 'current_password' => ['required', 'current_password'], 'password' => ['confirmed', new UserPassword()], ], [ 'password.confirmed' => ':attribute の入力が確認用と一致しません。', ], [ 'current_password' => '現在のパスワード', 'password' => '新しいパスワード', ] ); $request->user()->update([ 'password' => $validated['password'], ]); return back(); } }
独自Rule Validator
ここでもAttributeのPlaceholderは使える。
<?php class UserPassword implements ValidationRule { private $min_length = 8; /** * Run the validation rule. * * @param \Closure(string, ?string=): \Illuminate\Translation\PotentiallyTranslatedString $fail */ public function validate(string $attribute, mixed $value, Closure $fail): void { $rules = [ 'required', 'string', Password::min($this->min_length) ->mixedCase() ->numbers() ->symbols(), ]; $messages = [ ':attribute は必須です。', ':attribute は文字列で入力してください。', ':attribute は' . $this->min_length . '文字以上で、大文字・小文字・数字・記号を含める必要があります。', ]; foreach ($rules as $key => $rule) { $validator = Validator::make( [$attribute => $value], [$attribute => [$rule]], ); if ($validator->fails()) { $fail($messages[$key] ?? self::class . " validation error"); } } } }
$failでエラーメッセージを配列に積んでいける。ただし、Inertia.jsではエラーメッセージ配列の最初の1つ目だけを送るのでちょっと工夫が必要。
ということでInteria.jsでの工夫
ちょっと工夫はRequestクラスに行う。これを継承していけばOK
<?php class InertiaRequest extends FormRequest { /** * Determine if the user is authorized to make this request. */ public function authorize(): bool { return false; } /** * Get the validation rules that apply to the request. * * @return array<string, \Illuminate\Contracts\Validation\ValidationRule|array<mixed>|string> */ public function rules(): array { return [ // ]; } /** * Inertia.jsはValidationエラーを最初の1つしか投げないので、改行でJOINしたものにする。 * */ protected function failedValidation(Validator $validator) { $errors = collect($validator->errors()->toArray()) ->map(fn($messages) => implode("\n", $messages)) ->toArray(); // Inertiaにキャッチさせず、ここでResponseExceptionを投げて同一ページ更新 throw new HttpResponseException( back()->withErrors($errors)->withInput() ); } }
何をしているかというと、改行コードでJOINしているだけ。受け取ったInertia.jsではそれをsplitして複数に見せれれば大丈夫。