【Laravel】FormRequestの入力チェックを実行する方法のあれこれ
こんにちは、スズキです。
今回はFormRequestの入力チェックの実行方法についての紹介です。
FormRequestの入力チェックを実行する場合、通常は以下のような利用の仕方をします。
ここでStoreRequestはIlluminate\Foundation\Http\FormRequestを継承したクラスを指しています。
上記の場合、storeメソッドが呼ばれた際に、StoreRequestに定義されたチェック内容を元に入力チェックが実行されます。
入力チェックでエラーが見つかった場合、Exceptionが発生するようになっており、catchしたException内容を元にLaravelがエラー用のレスポンスを返すようになっています。
なお、FormRequestの入力チェックはインスタンス生成の際に同時に実行されています。
よって、FormRequestの入力チェックを任意のタイミングで実行したい場合、以下のようにすることで実現できます。
(以下のソースは、先程のソースと同じ処理内容となります。)
先ほど紹介した方法の応用となりますが、基底のControllerクラスを用意しつつ、入力チェックは継承先クラスに応じた入力チェックを実行する方法です。
先ほどの内容を読めば方法に推測がつくと思うのでソースだけ提示します。
●基底Conttrolerクラス
●継承先Conttrolerクラス
複数のFormRequestの入力チェック内容を取得し、その結果をサーバレスポンスとして返す方法の紹介です。
本方法を利用するケースですが、実際に私が業務で利用したケースだと、
「通常保存時に必須項目が未入力の場合は一時保存実行の確認メッセージを表示する。OKが押されれば一時保存を実行」
という対応を行うことになった際に本方法が必要になりました。
本方法ですが、以下のようにすることで実現することができます。
要点としては、
フォーム側はajax処理が成功した際の部分だけ例として示します。
「var status = 422;」の部分ですが、FormRequestによる入力チェックエラーが発生した場合は、ステータスコードが422になるので、これを指定しています。
今回はFormRequestの入力チェックの実行方法についての紹介です。
FormRequestの入力チェックを任意のタイミングで実行する
ここでStoreRequestはIlluminate\Foundation\Http\FormRequestを継承したクラスを指しています。
class TestController extends Controller
{
public function store(StoreRequest $request)
{
// 〜〜略〜〜 //
}
}
上記の場合、storeメソッドが呼ばれた際に、StoreRequestに定義されたチェック内容を元に入力チェックが実行されます。
入力チェックでエラーが見つかった場合、Exceptionが発生するようになっており、catchしたException内容を元にLaravelがエラー用のレスポンスを返すようになっています。
なお、FormRequestの入力チェックはインスタンス生成の際に同時に実行されています。
よって、FormRequestの入力チェックを任意のタイミングで実行したい場合、以下のようにすることで実現できます。
(以下のソースは、先程のソースと同じ処理内容となります。)
class TestController extends Controller
{
public function store()
{
// 入力チェックを実行
$request = \App::make(StoreRequest::class);
// 〜〜略〜〜 //
}
}
継承先Controllerで指定したFormRequestの入力チェックを実行する
先ほどの内容を読めば方法に推測がつくと思うのでソースだけ提示します。
●基底Conttrolerクラス
class BaseTestController extends Controller
{
/**
* 登録処理用Request
*/
protected $storeRequestClass;
public function store()
{
// 継承先の入力チェック処理を実行
$request = \App::make($this->storeRequestClass);
// 〜〜略〜〜 //
}
}
●継承先Conttrolerクラス
class TestController extends BaseTestController
{
/**
* 登録処理用Request
*/
protected $storeRequestClass = StoreTestRequest::class;
}
複数のFormRequestの入力チェック内容を取得し、その結果をサーバレスポンスとして返す
複数のFormRequestの入力チェック内容を取得し、その結果をサーバレスポンスとして返す方法の紹介です。
本方法を利用するケースですが、実際に私が業務で利用したケースだと、
- 一時保存時の入力チェック → 必須チェックを除いた入力チェックを実行
- 通常保存時の入力チェック → 必須チェックを含む入力チェックを実行
「通常保存時に必須項目が未入力の場合は一時保存実行の確認メッセージを表示する。OKが押されれば一時保存を実行」
という対応を行うことになった際に本方法が必要になりました。
本方法ですが、以下のようにすることで実現することができます。
class TestController extends Controller
{
/**
* 入力値のチェックを行います。
* @return mixed
*/
public function check()
{
$draftValidateErrors = null;
$storeValidateErrors = null;
// 一時保存用入力チェック実行
try {
\App::make(StoreTestDraftRequest::class);
} catch (HttpResponseException $e) {
$draftValidateErrors = json_decode($e->getResponse()->getContent(), true);
}
// 通常保存用入力チェック実行
try {
\App::make(StoreTestRequest::class);
} catch (HttpResponseException $e) {
$storeValidateErrors = json_decode($e->getResponse()->getContent(), true);
}
// チェック結果を返す
return response()->json([
'draftValidateErrors' => $draftValidateErrors,
'storeValidateErrors' => $storeValidateErrors,
], 200);
}
}
要点としては、
- FormRequestのインスタンスを生成し、入力チェックを実行
- エラーがあればExceptionが発生するのでこれをtry-catchし、入力チェックエラー情報を取得
- エラー情報にかかっているjson_encodeを元に戻すために、json_decodeを実行
フォーム側はajax処理が成功した際の部分だけ例として示します。
function onSuccessPreCheck (data, status, headers, config) {
var draftValidateErrors = data.draftValidateErrors
var storeValidateErrors = data.storeValidateErrors;
var isSuccessDraftValidate = (draftValidateErrors == null);
var isSuccessStoreValidate = (storeValidateErrors == null);
// 通常保存入力チェック成功時
if(isSuccessStoreValidate) {
// 通常保存用の処理を実行
storeProcess();
}
else {
// 一時保存用の入力チェックに失敗している場合
if(!isSuccessDraftValidate) {
// 通常保存用入力チェックのエラー結果を反映
var status = 422;
setErrors(storeValidateErrors, status, headers, config);
return;
}
// 「OK」の場合
if (window.confirm("未入力の必須項目があります。一時保存を行いますか?")) {
// 一時保存用の処理を実行
draftProcess();
}
// 「キャンセル」の場合
else {
// 通常保存用入力チェックのエラー結果を反映
var status = 422;
setErrors(storeValidateErrors, status, headers, config);
return;
}
}
}
「var status = 422;」の部分ですが、FormRequestによる入力チェックエラーが発生した場合は、ステータスコードが422になるので、これを指定しています。