LoginSignup
0
1

More than 3 years have passed since last update.

Laravelで簡単なCMSを作成(フォームリクエストでバリデーション)

Last updated at Posted at 2021-05-05

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

ArticlesRequest.php
<?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

ArticlesRequest.php
public function messages()
{
    return [
        'title.required' => 'タイトルを入力してください',
        'body.required' => '本文は入力必須です',
    ];
}

バリデーションルールの実行

コントローラメソッドで作成したArticlesRequestクラスをタイプヒントで指定することで、コントローラメソッドが実行される前にバリデーションが実行されます。
https://readouble.com/laravel/8.x/ja/validation.html#creating-form-requests

ArticlesController.php
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

add.blade.php
<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

add.blade.php
<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のルールを紹介しているので、これを使ってみます。

UpperCase.php
<?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.';
    }
}

カスタムルールの適用

ルールオブジェクトをほかのバリデーションルールと同様に指定します。

ArticleRequest.php
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

ArticleRequest.php
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',
    ];
}
0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1