バックエンドを触るなら、ユーザーの入力内容を「ふるいにかける」という処理である「バリデーション」は避けて通れない道かと思います。
PHPのフレームワークであるLaravelは自作のバリデーションを少ない労力で作成することが出来て、導入も簡単!
なはずなのですが、カスタムのバリデーションを適用したら、なんでか処理が行われない。バリデーションが発火しない!
というかバックのメソッド呼ばれてない・・・?みたいな現象を起こすことが(私は!)多々あります。
この記事を書いてる時点で、Laravelとは1年くらいの付き合いなのですが、それでもちょこちょこやってしまうミスなので、備忘録的にその原因・確認すべき点などをまとめたいと思います。
前提
【使用するFW】
Laravel
【状況】
カスタムリクエストを作成済み。
当たり前ですが、カスタムリクエストとしてバリデーションを自作していないわよ。。ってのはアレなので、そういう方はまず公式やブログなどを使いつつ、カスタムリクエストを作成してください。
確認すべき点
わかっている方には当たり前でしょうが、確認すべき点を先にまとめます。これが1つでも当てはまるならエラーもしくはエラーは出ないが期待した動作にならない。みたいなことになります。
ちなみに「送信ボタンは押せて、エラーも出ないのに、バリデーション(またはメソッド)が発火しない・・・?」みたいな方は③を見てください。
① ルートを定義していない
エラーが出るパターンです。
例えばユーザー情報を入力するフォームから送信される先のメソッドを用意していない。
ルートがない。
どっちもあるけど、色々不具合がある。
みたいなパターンなので、そりゃバリデーションかからんわな。って話です。
見出しとズレるけど、@csrf忘れとか、画像を扱う場合に「enctype="multipart/form-data"」が抜けている。パターンなんかもあったりします。
<form method="POST" action="{{ route('user.profile') }}" enctype="multipart/form-data"> // <- enctype="multipart/form-data"がないと画像扱えない
@csrf <- コレないと419エラーになる
この辺りは「フォーム送信!せいや!」ってやるとエラーページが出るので、そのエラーを解決すれば問題なく動作する方向に向かうはずです。
② リクエストを適用できていない
意外と忘れがちだったりする(かもしれません)ので一応。
せっかくカスタムのリクエストを作っても適用させなきゃ意味がないよね。って話です。
public function update(ProfileRequest $request): RedirectResponse // ProfileRequest(自作したバリデーションのリクエスト)を適用
{
// アップデートの処理
return redirect()->route('home')->with('status', '更新が完了しました!');
}
これも適用はしたけど、USE忘れてる。とかならエラーになるので比較的わかりやすいかな。と思います。
まぁ・・・これはあまりやらないかな。と思いつつ、Laravel初学者の同期が数時間悩んでいたので、見せてもらったらこのパターンだった。という私の実体験に基づいて、一応残しておきます。
初めての頃はエラーが出るとパニックになりがちだし、調べ方も下手だったりするので、割と沼るポイントなのか・・・🤔とも思ったり思わなかったり。
③ カラム名が違う。もしくは不足してるなど
コレは私もよくやります。いまだに、毎回と言っていいほどやります。
例えば、以下のような感じで、ユーザー情報をバリデーションするためのリクエストを作っていたとします。
class ProfileRequest extends FormRequest
{
public function authorize(): bool
{
return true; // これTRUEにしないと適応されない
}
public function rules(): array
{
return [
'name' => 'required|string|max:100',
'birthday' => 'required',
'email' => ['required', 'string', 'email', 'max:100', Rule::unique('users')->ignore(Auth::id(), 'id')],
];
}
....省略
みたいな感じにしているのに、フォーム側では・・・。
<form method="POST" action="{{ route('update', $user->id]) }}" enctype="multipart/form-data">
@method('PUT')
@csrf
{{-- 生年月日 --}}
<ul>
<li>生年月日(必須)</li>
<li>
<label>
年:
<select name="year" data-year="{{ $user->year }}"></select>
</label>
<label>
月:
<select name="month" data-month="{{ $user->month }}"></select>
</label>
<label>
日:
<select name="day" data-day="{{ $user->day }}"></select>
</label>
</li>
@error('birthday')
<p>{{ $message }}</p>
@enderror
</ul>
.....以下略
みたいになっているとエラーは出ず、「POST送信してる?よく分からないがエラー画面にはならないけど。んーでもバリデーションのエラーメッセージも出ないし、メソッドも呼ばれないし・・・。」みたいなことになります。
仮に
public function update(ProfileRequest $request): RedirectResponse
{
dd('呼ばれてます?');
return redirect()->route('home')->with('status', '更新が完了しました!');
}
みたいにしてもこのメソッド呼ばれない。
それもそのはず。だって「birthday」なんてカラムはフォームにないのだから。
自作したバリデーションルールでは「birthday」としてるけど、フォームから送信されてくるリクエストの中身は「year」「month」「day」と分かれています。
そりゃエラーメッセージも出ないですよね。(エラーディレクティブは「birthday」なので)
そして「year」「month」「day」のそれぞれのルールがないので、ここでバリデーションに引っかかり、リダイレクトされる(はず)のでメソッドも呼ばれません。
なので、見かけ上エラーも出ないし
バリデーションにも引っかかってないけど、処理が行われない・・・。なんでやねん。
みたいなことになります。
これを解決するために、例えば以下のように、バリデーションルールとフォームのカラムが一致するように変えてあげる必要があります
<form method="POST" action="{{ route('update', $user->id]) }}" enctype="multipart/form-data">
@method('PUT')
@csrf
{{-- 生年月日 --}}
<ul>
<li>生年月日(必須)</li>
<li>
<label>
年:
<select name="year" data-year="{{ $user->year }}"></select>
</label>
@error('year')
<p>{{ $message }}</p>
@enderror
<label>
月:
<select name="month" data-month="{{ $user->month }}"></select>
</label>
@error('month')
<p>{{ $message }}</p>
@enderror
<label>
日:
<select name="day" data-day="{{ $user->day }}"></select>
</label>
@error('day')
<p>{{ $message }}</p>
@enderror
</li>
</ul>
.....以下略
class ProfileRequest extends FormRequest
{
public function authorize(): bool
{
return true;
}
public function rules(): array
{
return [
'name' => 'required|string|max:100',
'year' => 'required|digits:4',
'month' => 'required|digits_between:1,2',
'day' => 'required|digits_between:1,2',
'email' => ['required', 'string', 'email', 'max:100', Rule::unique('users')->ignore(Auth::id(), 'id')],
];
}
....以下略
まとめ
と、まぁLaravelを使いこなしている方からすると「・・・」みたいな、しょーもないものなのですが、初学者や不慣れな方は割とやりがちなミスだと思います。
冷静に見るとそりゃそうだわ。となることでも焦っていたり、見落としたりでやることがあります。
エラーが出るものならミスにも気づきやすいですが、③みたいにスン・・・ってパターンもあるので、私含めお互いに気をつけましょう。
同じような現象に悩んでいる方の解決の手助けになったら嬉しいニャ