Laravelのフォームリクエスト: prepareForValidation
- 2022年3月18日
- 技術情報
今回は、Laravelで検証を行う前にリクエストデータを操作することについて話したいと思います。
フォームのリクエスト例
まず、記事の投稿を保存するためのフォームリクエストの例から見てみましょう。入力に適用されるルールに注目してください。
<?php
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
class StoreRequest extends FormRequest
{
/**
* Get the validation rules that apply to the request.
*
* @return array
*/
public function rules()
{
return [
'title' => 'required|max:200',
'body' => 'required',
'tags' => 'required|array|max:10',
'is_published' => 'required|boolean',
'author_name' => 'required',
];
}
}
ここで、ユーザーが投稿を作成するためにフォームを送信し、次のような入力データを渡したと仮定します。
[
'title' => 'My articles post',
'body' => 'This is the <script>alert('Alert!')</script> articles body.',
'tags' => 'laravel,code,updates',
'is_published' => 'true',
'author_name' => 'Ami',
]
tagsはカンマ区切りの値のリストとしてフロントエンドから送信され、is_publishedの入力は文字列として解釈されます。どちらも、コンテンツの観点からは正しいにもかかわらず、形式が正しくないだけで検証は失敗します。
さらに、titleにタイプミスがあり、本文に悪意のあるコードが含まれているように見えます。技術的にはこれらはバリデーションの問題ではないと言えますが、ユーザーを自分自身から救い、アプリケーションを保護する手助けをすることは可能です。
prepareForValidation
このメソッドはprepareForValidationという適切な名前で、デフォルトのアクションを持ちません。つまり、オーバーライドするためだけに置かれたものです。
protected function prepareForValidation()
{
// no default action
}
ベースとなる FormRequest クラスは Request クラスを継承しているので、 merge ヘルパーメソッドにアクセスし、必要な入力値だけを更新することができます。また、入力値そのものにクラスのプロパティのようにアクセスすることもできます。
protected function prepareForValidation()
{
$this->merge([
'title' => fix_typos($this->title),
'body' => filter_malicious_content($this->body),
'tags' => convert_comma_separated_values_to_array($this->tags),
'is_published' => (bool) $this->is_published,
]);
}
値はリクエスト自体で更新されるので、バリデーションを行った後にコントローラでどのようにアクセスしても、操作された値が戻ってくることになります。
[
'title' => 'My blog post', // 誤字を修正しました!
'body' => 'This is the post body.', //悪質なコンテンツは削除されました!
'tags' => ['laravel', 'code', 'updates'], // 配列になりました!
'is_published' => true, // 今はブール値です!
'author_name' => 'Ami', // 相変わらずです。
今回はということで終わります。
By Ami
asahi at 2022年03月18日 10:00:00