😸
[Laravel]バリデーションクラスを作成して、コントローラーから処理を切り離す[バリデーション]
SkinnyContollerを目指す
- 環境
Amazon Linux 2
Composer version 2.3.9
Laravel Framework 9.19.0
PHP 8.0.18
上記のSkinnyControllerとはなにかと一言でいうと、
「Controller内にビジネスロジックは書かずに、Viewを返す責任のみを負うべき」
※単一責任の法則(クラスにも言えることです)
これを達成するためにいくつかの手法が存在します。
①DBに関するロジックは、モデルに入れて Eloquent を優先して使用する
②ビジネスロジックはサービスクラスの中に書いて、コンストラクタ or Facades で呼ぶ
③バリデーションはリクエストクラスに書く
今回は、③の「バリデーションはリクエストクラスに書く」の実施方法を書いていこうと思います。
Validation の書き方は3種類
Validation1Controller.php
public function store(Request $request)
{
// リクエストデータの受け取り
$data = $request->all();
// バリデーションの実施
$validated = $request->validate([
'title' => 'required|unique:posts|max:255',
'body' => 'required',
]); // rulesは、 |:ヴァーティカルバー で区切るか []:配列 としても設定できます。
return view();
}
Validation2Controller.php
// Validatorクラスを使用するため
use Illuminate\Support\Facades\Validator;
public function store(Request $request)
{
// リクエストデータの受け取り
$data = $request->all();
// バリデーションの実施
// ルールの設定
$validation_rules = [
'title' => 'required|string|max: 255',
'age' => 'numeric',
];
// エラーメッセージのカスタマイズ
$validation_message = [
'required' => ':attributeは必須です',
'title.string' => ':attributeが不正な値です',
'age.max' => ':attributeは数値での入力をお願いします',
];
// 各リクエストの名称 >> エラーメッセージの:attributeに入る文字です。
$validation_attribute = [
'title' => 'タイトル',
'age' => '年齢',
];
// バリデーションエラー発生時にリダイレクトする
if ($validator->fails()) {
return redirect('post/create')
->withErrors($validator)
->withInput();
}
// バリデーション済みデータの取得
$validated = $validator->validated();
// バリデーション済みデータの一部を取得
$validated = $validator->safe()->only(['name', 'email']);
$validated = $validator->safe()->except(['name', 'email']);
return view();
}
リクエストクラスを作成することで、コントローラーの処理が走る前にバリデーションを
実施するので、コードの可視性が向上する
リクエストクラスの作成,
$ php artisan make:request TestRequest
/App/Http/Request内に生成されます。
Validation3Controller.php
// リクエストクラスの呼び出し
use App\Http\Request\TestRequest;
public function store(TestRequest $request) // TestRequestを引数に設定する
{
// バリデーション済みデータを取得
$data = $request->all();
return view();
}
TestRequest.php
<?php
namespace App\Http\Request;
// FormRequestを継承します。
use Illuminate\Foundation\Http\FormRequest;
class TestRequest extends FormRequest
{
/**
* リダイレクト先の指定
* $redirect = '[Redirect url]'
* $redirectRoute = '[Redirect Routing Name]'
* $redirectAction = '[Redirect to Controller Action]'
*
* 動作するfunction >> 継承元の FormRequest::getRedirectUrl()
*
*/
protected $redirect = '/post_top';
protected $redirectRoute = 'post.post_top';
protected $redirectAction = '';
/**
* Determine if the user is authorized to make this request.
* ユーザーがこの要求を行うことを許可されているかどうかを判別
*
* @return bool
*/
public function authorize()
{
// falseを返すと 403: This action UnAuthorized が返される
return true;
}
/**
* Get the validation rules that apply to the request.
* リクエストに適用される検証ルールを定義:取得
*
* @return array<string, mixed>
*/
public function rules()
{
return [
'title' => 'required|string|max: 255',
'age' => 'numeric',
];
}
/**
* 定義済みバリデーションルールのエラーメッセージ取得
*
* @return array
*/
public function messages()
{
return [
'required' => ':attributeは必須です',
'title.string' => ':attributeは不正な値です',
'title.max' => ':attributeは255文字以下です',
];
}
/**
* バリデーションエラーのカスタム属性の取得
*
* @return array
*/
public function attributes()
{
return [
'title' => 'タイトル',
'age' => '年齢',
];
}
/**@Override FormRequest->validationData() : array
* >> バリデーションの直前に前処理を挟む場合
*
* @return array
*/
public function validationData()
{
$data = $this->all();
// 前処理:例えば全角英数字を半角に変換する
// if (isset($data['name']))
// $data['name'] = mb_convert_kana($data['name'], 'a');
return $data;
}
}
エラーメッセージはどうやって受け取るのか
バリデーションエラー発生時にリダイレクトが行われます、
この時に withInput() を使用することによって、セッション情報に書き込まれます。
このバリデーションのセッション情報は、
session('_old_input');
で確認することができます。
TestRequest.php
~~~~~~~~~~
if ($validator->fails()) {
return redirect('post/create')
->withErrors($validator) // エラーメッセージ
->withInput(); // >> session('_old_input')へ書き込み;
}
~~~~~~~~~~
- blade.php での受け取り
post_top.blade.php
// 値の受け取りは、 old()ヘルパー
<input type="hidden" name="title" value="{{ old('title') }}">
// エラーメッセージを一括で受け取る
@if ($erros->any()) // エラーメッセージがあれば,,,
@foreach ($erros->all() as $error) // foreachでエラー内容を表示
<p>{{ $error }}</p>
@endforeach
@endif
// 直接リクエスト名で関連するエラーメッセージを呼び出す
@error('title')
// title.required でもいいですし、
// title.* でtitleに関するエラーメッセージを全てという意味になります。
<p>{{ $message }}</p>
@error
クロージング
次回は、サービスクラスへビジネスロジックを移動させる、Facades, ServiceProviderを利用した
簡易的な呼び出しを書いていこうと思います。
Discussion