2
1

More than 3 years have passed since last update.

Laravel の Form Request Validation と Yii の Model を継承したフォームクラスの違いについて

Posted at

はじめに

Laravel と Yii どちらともにアクション毎にフォームのバリデーションを分けたいとき、Laravel では Form Request Validation、Yii では Model を継承したフォームクラスを使えるんですが、役割に若干の違いがあるので、そこらへんをまとめたいと思います。

環境

Laravel 6.x
Yii 2.x

Laravel Form Request Validation

モデル:

app/Models/Post.php
declare(strict_types=1);

namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class Post extends Model
{
    protected $table = 'post';

    protected $fillable = [
        'title',
        'content',
    ];

    // ...
}

Form Request:

app/Http/Requests/PostStore.php
declare(strict_types=1);

namespace App\Http\Requests;

use Illuminate\Contracts\Validation\Validator;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Validation\ValidationException;

class PostStore extends FormRequest
{
    public function authorize(): bool
    {
        return true;
    }

    public function attributes(): array
    {
        return [
            'title' => 'Title',
            'content' => 'Content',
        ];
    }

    public function rules(): array
    {
        return [
            'title' => 'required|max:100',
            'content' => 'required|max:10000',
        ];
    }

    protected function prepareForValidation(): void
    {
        // バリデーション前に何かを処理したい場合、ここに書くことができる
    }

    protected function failedValidation(Validator $validator): void
    {
        // バリデーション失敗時に何かを処理したい場合、ここに書くことができる

        throw new ValidationException($validator);
    }

    protected function passedValidation(): void
    {
        // バリデーションが通ったあとに何かを処理したい場合、ここに書くことができる
    }
}

コントローラー:

app/Http/Controllers/PostController.php
declare(strict_types=1);

namespace App\Http\Controllers;

use App\Http\Requests\PostStore;
use App\Models\Post;
use Illuminate\Http\RedirectResponse;
use Illuminate\View\View;

class PostController extends Controller
{
    // ...

    public function create(): View
    {
        return view('post.create');
    }

    public function store(PostStore $request): RedirectResponse
    {
        Post::create($request->all());

        return redirect()->route('post.index');
    }
}

Yii の Model を継承したフォームモデル

モデル:

models/Post.php
declare(strict_types=1);

namespace app\models;

use yii\db\ActiveRecord;

/**
 * @property int $id
 * @property string $title
 * @property string $content
 */
class Post extends ActiveRecord
{
    public static function tableName(): string
    {
        return 'post';
    }
}

フォームモデル:

models/PostCreateForm.php
declare(strict_types=1);

namespace app\models;

use yii\base\Model;

class PostCreateForm extends Model
{
    public $title;
    public $content;

    public function attributeLabels(): array
    {
        return [
            'title' => 'Title',
            'content' => 'Content',
        ];
    }

    public function rules(): array
    {
        return [
            [['title', 'content'], 'trim'],
            [['title', 'content'], 'required'],
            ['title', 'string', 'max' => 100],
            ['content', 'string', 'max' => 10000],
        ];
    }

    public function beforeValidate(): bool
    {
        // バリデーション前に何かを処理したい場合、ここに書くことができる

        return parent::beforeValidate();
    }

    public function afterValidate(): void
    {
        // バリデーション後に何かを処理したい場合、ここに書くことができる

        parent::afterValidate();
    }

    public function save(): bool
    {
        // 処理が単純な場合、beforeValidate(), afterValidate() を使わずに validate() の前後に処理を書くこともできる
        if ($this->validate()) {
            // 例えばデータ保存処理

            // データ保存後に何かを処理したい場合、ここに書くことができる

            return true;
        }

        // バリデーションの失敗時に何かを処理したい場合、ここに書くことができる

        return false;
    }
}

コントローラー:

controllers/SiteController.php
declare(strict_types=1);

namespace app\controllers;

use app\models\PostCreateForm;
use Yii;
use yii\web\Controller;
use yii\web\Response;
// ...

class SiteController extends Controller
{
    // ...

    /**
     * @return string|Response
     */
    public function actionCreate()
    {
        $post = new PostCreateForm;

        if ($post->load(Yii::$app->request->post()) && $post->save()) {
            return $this->redirect(['index']);
        }

        return $this->render('index', [
            'post' => $post,
        ]);
    }
}

まとめ

Laravel の Form Request Validation は「ユーザーがリソースを更新する権限を持っているかの判断」と「ユーザーのフォーム入力に対してのバリデーション処理」と「バリデーション失敗時のリダイレクト処理」という役割を担っていて、Yii のモデルを継承したフォームクラスは、基本的に「ユーザーのフォーム入力に対してのバリデーション処理のみ」がメインで、あとの諸々の処理 (ログイン処理であったり、データの保存処理であったり) は適当にそこでやってくれという感じで、わりとモデルとの関わりが濃い印象でした (Model を継承しているので当たり前ですが) 。

リンク

Laravel Form Request Validation
Yii フォームを扱う

2
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
2
1