苗木「フォームからの送信値が全部string型になる……」
フォームからのデータは、いちいちキャストしないといけない?
苗木「モノクマに頼まれた、 学級裁判の議事録を投稿するシステムを作ろう」
苗木「必要なデータは、とりあえずこれかな」
・タイトル
・本文
・参加人数
・公開/非公開設定
苗木「HTML部分は、こんな風にして……」
<form method="post" action="/create">
@csrf
タイトル:<input type="text" name="title">
<br>
本文:<textarea name="body"></textarea>
<br>
参加人数:<input type="text" name="number_of_people">
<br>
<input type="hidden" name="is_public" value="0">
公開/非公開設定:<label><input type="checkbox" name="is_public" value="1">公開する</label>
</form>
苗木「POSTしたデータを、コントローラーで処理しよう! バリデーションは、フォームリクエストでやろうかな」
class PostController extends Controller
{
public function store(StoreRequest $request)
{
// バリデーションチェックを通ったデータだけ取得
$data = $request->validated();
// DBに登録
Post::create([
'title' => $data['title'], // タイトル
'body' => $data['body'], // 本文
'number_of_people' => (int) $data['number_of_people'], // 参加人数
'is_public' => (boolean) data['is_public'], // 公開/非公開設定
]);
// 一覧ページにリダイレクト
return redirect('/index')->with('message', '議事録を作成しました');
}
}
class StoreRequest extends FormRequest
{
public function rules()
{
return [
'title' => ['required', 'string', 'max:255'],
'body' => ['required', 'string'],
'number_of_people' => ['required', 'integer'],
'is_public' => ['required', 'boolean'],
];
}
}
苗木「$request->validated();
は、バリデーション後のデータを配列で持ってきてくれるから、便利だね」
苗木「それにしても、毎回思うんだけど……DBに登録するときのココ」
// DBに登録
Post::create([
'title' => $data['title'], // タイトル
'body' => $data['body'], // 本文
'number_of_people' => (int) $data['number_of_people'], // 参加人数
'is_public' => (boolean) data['is_public'], // 公開/非公開設定
]);
苗木「フォームから受け取った値は全部文字型だから、整数型は(int)、論理型は(boolean)みたいに、キャストしないといけないんだよね。これ、ちょっと面倒臭いなぁ」
葉隠「なーに言ってんだ、苗木っち。そんなの、こうすりゃいいんだべ!」
// DBに登録
Post::create([
'title' => $data['title'], // タイトル
'body' => $data['body'], // 本文
'number_of_people' => $data['number_of_people'], // 参加人数
'is_public' => $data['is_public'], // 公開/非公開設定
]);
葉隠「キャストなんかしなくても、Laravelっちがよしなにやってくれるべ!」
苗木「うーん……それはそうなんだけど……。やっぱり、型はちゃんと意識したいし、処理の途中で他のメソッドに値を渡すときは、やっぱりキャストしないとダメだよね?」
フォームリクエストから、キャスト済のデータを取得
霧切「苗木くんのクセに生意気なことを言うのね」
苗木「霧切さん!」
霧切「そんなときは、ココに一工夫加えればいいのよ」
// バリデーションチェックを通ったデータだけ取得
$data = $request->validated();
霧切「このvalidated()
は、フォームリクエストの親クラス……つまり、FormRequestクラスのメソッドよ。苗木君、ここまで言えばわかるわね?」
苗木「いや、わかんないけど……」
霧切「StoreRequestクラスで、validatedメソッドをオーバーライドするのよ」
class StoreRequest extends FormRequest
{
public function rules()
{
return [
'title' => ['required', 'string', 'max:255'],
'body' => ['required', 'string'],
'number_of_people' => ['required', 'integer'],
'is_public' => ['required', 'boolean'],
];
}
// ココでオーバーライド
public function validated()
{
// バリデーションチェックを通ったデータだけ取得
$validated = $this->validator->validated();
// キャストしたデータをarra_mergeで上書き
return array_merge($validated,[
'number_of_people' => (int) $this->number_of_people,
'is_public' => (boolean) $this->is_public,
]);
}
}
苗木「そっか! そうすれば、$request->validated();
で取得した段階で、既にキャストされてるんだね! 後は、葉隠クンがやったように、何も考えずにデータを渡せるんだ!」
class PostController extends Controller
{
public function store(StoreRequest $request)
{
// バリデーションチェックを通ったデータだけ取得
$data = $request->validated();
// DBに登録
Post::create([
'title' => $data['title'], // タイトル
'body' => $data['body'], // 本文
'number_of_people' => $data['number_of_people'], // 参加人数
'is_public' => $data['is_public'], // 公開/非公開設定
]);
// 一覧ページにリダイレクト
return redirect('/index')->with('message', '議事録を作成しました');
}
}
霧切「余談だけど、フォームリクエストで論理型にキャストするときのココ」
'is_public' => (boolean) $this->is_public
霧切「Laravel6系以降なら、論理型を取得するための専用メソッドも用意されているわ」
'is_public' => $this->boolean('is_public')
// 普通のリクエストでも
'is_public' => $request->boolean('is_public')
苗木「ありがとう、霧切さん!フォームリクエストって、奥が深いんだね!」
霧切「ええ、バリデーションだけじゃなくて、色々なことができるわ。興味があったら、調べてみてちょうだい」
Discussion