Framework

Laravel5 Form Request Validationによるコントローラの軽量化

投稿日:

フォームのビジネスロジック(検証や保存)をコントローラに書くと、どうでも良いコードでコントローラが重くなってくる。フォームが複数ある場合、だいたい似たり寄ったりのコードが量産されていく。本エントリでは、Laravel5 の Form Request Validation によってコントローラからバリデーションロジックを完全分離する方法について記述する。

Form Request Validation - バリデーションの分離

流れは以下の通り。

  • App\Http\Requests\Requestクラスを派生し、ContactRequestクラスを作成する。
  • コントローラメソッドにて、App\Http\Requests\Requestクラスのインスタンスではなく ContractRequestクラスのインスタンスを受けるようにする。
  • コントローラメソッドに入ったときには既にContactRequestクラスによるバリデーションが完了していて、データが正しい前提で処理できる。

ContactRequestクラス、ContactRequestTraitクラスの例を以下に示す。

<?php

namespace App\Http\Requests;

class ContactRequest extends Request
{
    use ConfirmRequestTrait;

    /**
     * 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 [
            'name'    => 'required',
            'email'   => 'required|email',
            'subject' => 'required',
            'content' => 'required',
        ];
    }

    /**
     * Set custom messages for validator errors.
     *
     * @return array
     */
    public function messages()
    {
        return [
            //
        ];
    }

    /**
     * Set custom attributes for validator errors.
     *
     * @return array
     */
    public function attributes()
    {
        return [
            'name'    => 'お名前',
            'email'   => 'メールアドレス',
            'subject' => '件名',
            'content' => '内容',
        ];
    }
}
<?php

namespace App\Http\Requests;

use Illuminate\Contracts\Validation\Validator;

trait ConfirmRequestTrait
{
    /**
     * Set custom messages for validator errors.
     *
     * @param \Illuminate\Contracts\Validation\Factory $factory
     *
     * @return \Illuminate\Contracts\Validation\Validator
     */
    public function validator($factory)
    {
        // 値検証前の処理
        if (method_exists($this, 'beforeValidate')) {
            $this->beforeValidate();
        }

        $validator = $factory->make(
            $this->all(),
            $rules,
            $this->messages(),
            $this->attributes()
        );

        $validator->after(function ($validator) {
            $failed = $validator->failed();

            // 値検証後の処理
            if (method_exists($this, 'afterValidate')) {
                $this->afterValidate($validator);
            }
        });

        return $validator;
    }

    /**
     * Format the errors from the given Validator instance.
     *
     * @param  \Illuminate\Contracts\Validation\Validator  $validator
     *
     * @return array
     */
    protected function formatErrors(Validator $validator)
    {
        $errors = parent::formatErrors($validator);
        return $errors;
    }
}

Form Request Validation - コントローラ側

ポイントは、storeメソッドの引数に ContactRequestヒントが渡されていること。sotreメソッドに入る前にContactRequestによりバリデーションが実行され、バリデーションに成功した時に限り、sotre()メソッドに入る。バリデーションが失敗すると、その前のアドレスにリダイレクトされる。コントローラから一切のバリデーションロジックを排除できた。

<?php

namespace App¥Http¥Controllers;
use App¥Http¥Requests¥ContactRequest;
use App¥Repositories¥ContactRepository;

class ContactController extends Controller
{
/**
/* @var ContactRepository
*/
protected $repository;

/**
/* @constructor
/* param ContactRepository $repository
*/
public function __construct(ContactRepository $repository)
{
$this->repository = $repository;
}

/*
*
*/
public function index()
{
...
}

/**
* @var ContactRequest $request
*
*/
public function store(ContactRequest $request)
{

}

}

-Framework

Copyright© ikuty.com , 2018 AllRights Reserved Powered by AFFINGER4.