【PHP】Valitronの使い方と独自ルールの追加方法

#概要
PHPのバリデーションライブラリ[Valitron](https://github.com/vlucas/valitron)を使ったときのメモです。

#準備
[Valitron：公式Github](https://github.com/vlucas/valitron)

Composerでインストールします。
インストールしたいディレクトリで以下を実行します。

```bash
php composer.phar require vlucas/valitron
```

　
・vendor/vlucas（ディレクトリ）
・composer.json
・composer.lock

が生成されていればインストール完了です。

#実装

```php
// $dataには検証したいデータの配列が入る想定（POSTの値等）
$data = [
    'name' => '山田太郎',
    'kana' => 'ヤマダタロウ',
    'email' => 'hoge@example.com',
];

// ライブラリ読み込み
require_once('path/to/vendor/autoload.php');

// メッセージの日本語化
Valitron\Validator::lang('ja');

// 検証する値を引数にインスタンスを生成
$validation = new Valitron\Validator($data);

// 項目名を設定
$validation->labels([
    'name' => '名前',
    'kana' => 'フリガナ',
    'email' => 'メールアドレス'
]);

// バリデーションルール
$validation->rule('required', ['name', 'kana', 'email'])
    ->message('{field}は必須項目です。');

$validation->rule('lengthMax', ['name', 'kana'], 50)
    ->message('入力可能な文字数は50字までです。');

$validation->rule('email', 'email')
    ->message('正しいメールアドレス形式で入力してください。');

$validation->rule('regex', 'kana', '/^[ 　ァ-ヴー]+$/u')
    ->message('カタカナで入力してください。');

// バリデーションの実行
if(!$validation->validate()) {
    echo 'バリデーションエラーです。';
}

// エラー内容の入った配列
var_dump($validation->errors());
```

　
複数のバリデーションに引っかかることもあるので、1つだけ返すようにしたりもします。

```php
public function validation($data)
{
    // 諸々のバリデーションの処理
    :
    $err_msg = [];
    if(!$validation->validate()) {
        foreach ($validation->errors() as $key => $value) {
            // 1つめのエラーだけを代入
            $err_msg[$key] = $value[0];
        }
    }
    return $err_msg;
}
```
　
**【項目名の設定】**
`$validation->labels`では、項目名の設定ができます。
message部分で{field}を使用する際、項目名設定が無い場合は配列のキー名がそのまま使用されるので、「nameは必須項目です」のようになります。

そのため、項目の別名（ラベル）を設定します。

　
**【エラーの結果】**
`$data`にルールに反する入力項目を入れた場合の`$validation->errors()`の中身です。
項目ごとに引っかかったバリデーションのエラーメッセージが格納されます。

```
array(3) {
  ["name"]=>
  array(1) {
    [0]=>
    string(45) "名前は必須項目です。"
  }
  ["kana"]=>
  array(2) {
    [0]=>
    string(47) "入力可能な文字数は50字までです。"
    [1]=>
    string(42) "カタカナで入力してください。"
  }
  ["email"]=>
  array(1) {
    [0]=>
    string(66) "正しいメールアドレス形式で入力してください。"
  }
}
```

#ルールについて
基本は[Valitron：公式Github](https://github.com/vlucas/valitron)に、すでに用意されているルールについて記載があります。
入力必須、文字数、パスワードなどの確認入力、正規表現などが用意されています。

また、`required`に関しては、半角スペースのみの場合はエラーになりますが、全角スペースは入力としてみなされるようです。

　
**【参考】**
以下でも分かりやすくルールや設定について書かれています。
・[シンプルで使いやすい！バリデーションライブラリ「Valitron」の使い方](https://tech.arms-soft.co.jp/entry/2019/10/30/090000)

#独自ルールの追加方法
独自のルールはインスタンスを生成する前に定義を行います。
今回は半角・全角スペースのみの入力をNGとするルールを作ります。

```validation.php
// 独自ルールの追加
Valitron\Validator::addRule('spaceOnly', function($field, $value) {
    // 値の半角・全角スペースを削除
    $replace = preg_replace('/[\s　]*/', '', $value);

    // 空でなければtrue
    if (!empty($replace)) {
        return true; // trueは必ず返す
    } else {
        return false;
    }
}, '空白文字のみの入力は出来ません。');

// 検証する値を引数にインスタンスを生成
$validation = new Valitron\Validator($data);

:
:

if (!empty($data[$name])) {
    $validation->rule('spaceOnly', $name, $data['name'])
        ->message('空白文字のみの入力は出来ません。');
}
```

　
**【独自ルールの判定】**
ルールに関数を渡して処理した結果でバリデーションをかけることができます。[公式の例](https://github.com/vlucas/valitron#adding-custom-validation-rules)のようにやってみましたが、falseのみを返す場合うまく挙動せず、基本的に独自ルールではtrueを返すか、どちらも明示的に返すのが良いかと思います。


**【エラーメッセージ】**
`addRule`の第三引数にはエラー時のメッセージを指定できます。
ただし、文頭にラベルが勝手に付きます。

例えば「お名前 空白文字のみの入力は出来ません。」のような出力になります。
{field}を使えばラベルの位置は変更可能です。

指定しない場合は「お名前 Invalid」となります。
なので、基本的には`$validation->ruleのmessage()`の方で指定が良いかと思います。

#参考
・[シンプルで使いやすい！バリデーションライブラリ「Valitron」の使い方](https://tech.arms-soft.co.jp/entry/2019/10/30/090000)
・[validatorjsとValitronのカスタムルールを作成する](https://armband.qrunch.io/entries/rWnXRICErSEElOC7)
・[PHP Valitron Validator::addRule Examples](https://hotexamples.com/examples/valitron/Validator/addRule/php-validator-addrule-method-examples.html)