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

  • 21
    いいね
  • 0
    コメント

本記事は 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

ひとこと

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

この投稿は Laravel Advent Calendar 20166日目の記事です。