Laravelで簡単なCMSを作成してみます。記事登録までの機能は下記の記事を参考に。
今回は新規登録する記事にバリデーション機能を追加します。Laravelのバリデーション機能には「フォームリクエスト」という独自のバリデーションクラスを作成し適用できる機能が用意されています。「フォームリクエスト」の利点は、コントローラメソッドにタイプヒンティングすることで、バリデーションロジックをコントローラメソッド内に記述する必要がなくなり、メソッドがスッキリすることです。
フォームリクエストクラス作成
artisan
コマンドでフォームリクエストのひな形を作成できます。
https://readouble.com/laravel/8.x/ja/validation.html#creating-form-requests
php artisan make:request ArticlesRequest
バリデーションルール作成
フォームリクエストクラスのrules
メソッドでバリデーションルールを定義します。
https://readouble.com/laravel/8.x/ja/validation.html#creating-form-requests
<?php
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
class ArticlesRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*
* @return bool
*/
public function authorize()
{
return true;
}
/**
* Get the validation rules that apply to the request.
*
* @return array
*/
public function rules()
{
return [
'title' => 'required|unique|max255',
'body' => 'required',
];
}
}
エラーメッセーのカスタマイズ
message
メソッドをオーバーライドすることでエラーメッセージをカスタマイズできます。
https://readouble.com/laravel/8.x/ja/validation.html#customizing-the-error-messages
public function messages()
{
return [
'title.required' => 'タイトルを入力してください',
'body.required' => '本文は入力必須です',
];
}
バリデーションルールの実行
コントローラメソッドで作成したArticlesRequest
クラスをタイプヒントで指定することで、コントローラメソッドが実行される前にバリデーションが実行されます。
https://readouble.com/laravel/8.x/ja/validation.html#creating-form-requests
use App\Http\Requests\ArticlesRequest;
public function create(ArticlesRequest $request)
{
$validated = $request->validated();
$article = Article::create([
'title' => $request->title,
'body' => $request->body,
'user_id' => Auth::id(),
'slug' => $request->title,
]);
// 中間テーブルにtagを登録
$article->tags()->attach($request->tags);
return redirect('/articles');
}
バリデーションエラーの表示
@error
ディレクティブを使用すると、特定の属性のバリデーションエラーメッセージが存在するか確認でき、$message
変数でエラーメッセージを取得できます。
https://readouble.com/laravel/8.x/ja/validation.html#the-at-error-directive
<label class="block">
<span class="text-gray-700">Title</span>
<input type="text" name="title" class="mt-1 block w-full @error('title') border-red-500 @enderror">
@error('title')
<p class="text-red-500 text-xs italic mt-3">{{ $message }}</p>
@enderror
</label>
<label class="block">
<span class="text-gray-700">Body</span>
<textarea class="mt-1 block w-full @error('body') border-red-500 @enderror" rows="3" name="body"></textarea>
@error('body')
<p class="text-red-500 text-xs italic mt-3">{{ $message }}</p>
@enderror
</label>
フォームの再取得
バリデーションエラーがあると直前のページにリダイレクトされます。直前のフォーム画面で入力された値は、old
メソッドまたはヘルパを使用することで取得できます。
https://readouble.com/laravel/8.x/ja/validation.html#repopulating-forms
<label class="block">
<span class="text-gray-700">Title</span>
<input type="text" name="title" class="mt-1 block w-full @error('title') border-red-500 @enderror" value="{{ old('title') }}">
@error('title')
<p class="text-red-500 text-xs italic mt-3">{{ $message }}</p>
@enderror
</label>
<label class="block">
<span class="text-gray-700">Body</span>
<textarea class="mt-1 block w-full @error('body') border-red-500 @enderror" rows="3" name="body">{{ old('body') }}</textarea>
@error('body')
<p class="text-red-500 text-xs italic mt-3">{{ $message }}</p>
@enderror
</label>
カスタムバリデーションルール
独自のバリデーションルールを定義できます。
https://readouble.com/laravel/8.x/ja/validation.html#custom-validation-rules
ルールオブジェクトを作成
artisan
コマンドでルールオブジェクトを作成します。
php artisan make:rule Uppercase
カスタムルール定義
LaravelのドキュメントではUpperCaseのルールを紹介しているので、これを使ってみます。
<?php
namespace App\Rules;
use Illuminate\Contracts\Validation\Rule;
class Uppercase implements Rule
{
/**
* Create a new rule instance.
*
* @return void
*/
public function __construct()
{
//
}
/**
* Determine if the validation rule passes.
*
* @param string $attribute
* @param mixed $value
* @return bool
*/
public function passes($attribute, $value)
{
return strtoupper($value) === $value;
}
/**
* Get the validation error message.
*
* @return string
*/
public function message()
{
return 'The :attribute must be uppercase.';
}
}
カスタムルールの適用
ルールオブジェクトをほかのバリデーションルールと同様に指定します。
public function rules()
{
return [
'title' => ['required', 'unique:users', 'max:255', new Uppercase],
'body' => 'required',
];
}
1回切りのカスタムルール作成
他のフォームでは使用しないルールは、ルールオブジェクトではなくクロージャを渡すことで実現できます。
https://readouble.com/laravel/8.x/ja/validation.html#using-closures
public function rules()
{
return [
// 'title' => 'required|unique:users|max:255',
'title' => [
'required',
'unique:users',
'max:255',
function ($attribute, $value, $fail) {
if (! preg_match('/^【.+】/u', $value)) {
$fail('【単語】見出し の形式でタイトルを書いてください');
}
}
],
'body' => 'required',
];
}