Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
Help us understand the problem. What is going on with this article?

Laravel でカスタムバリデーションとそのテスト

More than 3 years have passed since last update.

本記事は Laravel Advent Calendar 2016 の 6 日目の記事です。

はじめに

公式のカスタムバリデーションのドキュメントが今ひとつ分かりにくいので、手順をまとめることにした。
今回はサンプルとして ふりがな のバリデーションを作成する。

※以前に書いた通常バリデーションの応用
http://qiita.com/komatzz/items/422bcba9847ca3a79fe9

環境

  • CentOS 7
  • PHP 7
  • Laravel 5.3

カスタムバリデーション作成手順

サービスプロバイダー作成

php artisan make:provider ValidatorServiceProvider

作成されたクラスを以下のように編集。

app/Providers/ValidatorServiceProvider.php
namespace App\Providers;

use Illuminate\Support\ServiceProvider;
use Domain\CustomValidator;

class ValidatorServiceProvider extends ServiceProvider
{
    /**
     * Bootstrap the application services.
     *
     * @return void
     */
    public function boot()
    {
      \Validator::resolver(function ($translator, $data, $rules, $messages) {
          return new CustomValidator($translator, $data, $rules, $messages);
      });
    }

    /**
     * Register the application services.
     *
     * @return void
     */
    public function register()
    {
        //
    }
}

作成したサービスプロバイダーを設定ファイルに追加

config/app.php
'providers' => [
    ...

    App\Providers\ValidatorServiceProvider::class,

    ...

カスタムバリデーションのロジックを書くファイルを作成する

今回はdomainというディレクトリを作成し、その下にCustomValidator.phpを作成した。

domain/CustomValidator.php
namespace Domain;

class CustomValidator extends \Illuminate\Validation\Validator
{
  /**
  * ふりがなのバリデーション
  *
  * @param $attribute
  * @param $value
  * @param $parameters
  * @return bool
  */
  public function validateKana($attribute, $value, $parameters)
  {
      if (mb_strlen($value) > 100) {
          return false;
      }  

      if (preg_match('/[^ぁ-んー]/u', $value) !== 0) {
          return false;
      }

      return true;
  }
}

オートロードの設定

composer.json の psr-4 設定に にdomainディレクトリ配下をオートロードできるように追加する
※これに気づかなくてハマった

composer.json
...

"autoload": {
  "psr-4": {
      "App\\": "app/",
      "Domain\\": "domain/",
  }
}

...

エラーメッセージファイルに追加

resources/lang/ja/validation.php
return [
   ...

   'kana' => ':attributeはひらがなで入力をしてください。',

   ...

   'attributes' => [
       ...

        'family_name_kana' => 'ふりがな(せい)',
        'given_name_kana'  => 'ふりがな(めい)',

       ...
   ],

カスタムバリデーションを使う

使い方は通常のバリデーションと同じで、
'family_name_kana' => 'required|kana',
のように使いたいバリデーションを|区切りで指定すれば良い。

app/Http/Controllers/RegistersController.php
namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\Http\Requests;
use App\Http\Controllers\Controller;
use Validator;

class RegistersController extends Controller
{
    ...

    public function confirm(Request $request, $registerToken)
    {
        \Validator::make(
            [
                'family_name_kana' => trim($request->get('family_name_kana')),
                'given_name_kana'  => trim($request->get('given_name_kana')),
            ],
            [
                'family_name_kana' => 'required|kana',
                'given_name_kana'  => 'required|kana',
            ]
        }->validate();
    }
    return view('registers/registers_confirm');

    ...
}

バリデーション実施結果

valid_kana.png

ふりがな(せい)をカタカナで POST したので、ちゃんと引っかかっている。

テストコード作成

ちゃんとバリデーションできているかどうかテストするコードを書く。

tests/domain/validation/KanaTest.php
<?php

/**
 * かなのバリデーションのテストクラス
 */

namespace Tests\Domain\Validation;

use Validator;

class KanaTest extends \TestCase
{
    /**
     * 正常系テスト
     *
     * @dataProvider successParamsProvider
     * @param array $values
     */
    public function testSuccess($values)
    {
        $validator = \Validator::make(
            [
                'family_name_kana' => $values,
                'given_name_kana'  => $values,
            ],
            [
                'family_name_kana' => 'required|kana',
                'given_name_kana'  => 'required|kana',
            ]
        );

        $this->assertTrue(
            $validator->passes()
        );
    }

    /**
     * 正常系パラメータ用のデータプロバイダー
     *
     * @return array
     */
    public function successParamsProvider()
    {
        return [
            'ひらがな' => [
                'やきにくていしょく',
            ],
            '大きな文字列(かなは100文字まで)' => [
                str_repeat('あ', 100)
            ],
        ];
    }

    /**
     * 異常系テスト
     *
     * @dataProvider failParamsProvider
     * かなに不適切な文字が入力されている
     *
     * @param array $values
     */
    public function testFail($values)
    {
        $validator = \Validator::make(
            [
                'family_name_kana' => $values,
                'given_name_kana'  => $values,
            ],
            [
                'family_name_kana' => 'required|kana',
                'given_name_kana'  => 'required|kana',
            ]
        );

        $this->assertTrue(
            $validator->fails()
        );
    }

    /**
     * 異常系パラメータ用のデータプロバイダー
     *
     * @return array
     */
    public function failParamsProvider()
    {
        return [
            '数字' => [
                1,
            ],
            '漢字' => [
                '焼肉定食',
            ],
            'カタカナ' => [
                'ヤキニクテイショク',
            ],
            '大きな文字列(かなは100文字まで)' => [
                str_repeat('あ', 101),
            ],
            'NULL' => [
                null,
            ],
            '空' => [
                '',
            ],
            'スクリプト' => [
                '<script>alert(1);</script>',
            ],
            '\'' => [
                '\'',
            ],
            '/' => [
                '/',
            ],
            '<' => [
                '<',
            ],
            '¥' => [
                '¥',
            ],
        ];
    }
}

解説

  • ひらがな かつ、100文字以内かどうかをテストしている
  • PHPUnit のデータプロバイダーという機能を使うと簡潔にテストコードが書けて、失敗したときにどこで失敗したのか分かりやすい

image

ひとこと

これでバリデーション処理に関しては、ほとんど対応できるようになった。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away