BETA

`validatorjs` と `Valitron` のカスタムルールを作成する

投稿日:2020-08-16
最終更新:2020-08-16

JavaScript 側のバリデーションを validatorjs 、 PHP 側のバリデーションを vlucas/valitron で作成していたのですが、チェックボックスのバリデーションについてカスタムルールを作る必要が出てきたのでメモしておきます。

前提

フォームの例を以下に示します。

<form action="cockadoodledoo" method="post">  
    <label for="divinity" class="col-md-3 col-form-label text-right">  
        ご祭神  
    </label>  
    <div class="form-check form-check-inline">  
        <label class="form-check-label">  
            <input type="checkbox" class="form-check-input" id="divinity0" name="divinity[]" value="天村雲神・天水雲神・天御雲神">天村雲神・天水雲神・天御雲神  
        </label>  
        <label class="form-check-label">  
            <input type="checkbox" class="form-check-input" id="divinity1" name="divinity[]" value="天水分神・国水分神">天水分神・国水分神  
        </label>  
        <label class="form-check-label">  
            <input type="checkbox" class="form-check-input" id="divinity2" name="divinity[]" value="水波女神・水速女神">水波女神・水速女神  
        </label>  
        <label class="form-check-label">  
            <input type="checkbox" class="form-check-input" id="divinity3" name="divinity[]" value="綿津見神">綿津見神  
        </label>  
        <label class="form-check-label">  
            <input type="checkbox" class="form-check-input" id="divinity4" name="divinity[]" value="大己貴神">大己貴神  
        </label>  
        <label class="form-check-label">  
            <input type="checkbox" class="form-check-input" id="divinity5" name="divinity[]" value="阿須波神・波比岐神">阿須波神・波比岐神  
        </label>  
        <label class="form-check-label">  
            <input type="checkbox" class="form-check-input" id="divinity6" name="divinity[]" value="高皇産霊神">高皇産霊神  
        </label>  
        <label class="form-check-label">  
            <input type="checkbox" class="form-check-input" id="divinity7" name="divinity[]" value="伊邪那岐命・伊邪那美命">伊邪那岐命・伊邪那美命  
        </label>  
        <label class="form-check-label">  
            <input type="checkbox" class="form-check-input" id="divinity8" name="divinity[]" value="天御中主神">天御中主神  
        </label>  
    </div>  
</form>  

普通のチェックボックスですね。

ただし、今回はこれをそのまま処理するわけではありません

確認画面をモーダルで済ませたかったので、 JavaScript で一度チェックの入った値を取得し、カンマ区切りの文字列として保持、それを hidden パラメータにセットする、ということをしています。

つまり、実際は以下のような形でセットされます。

<form action="cockadoodledoo" method="post">  
    <input type="hidden" name="h_divinity" id="h_divinity" value="天水分神・国水分神,綿津見神,高皇産霊神">  
</form>  

この値をバリデーションしたい、と。

validatorjs

まずは JavaScript 側。 script タグで本体読み込み済みとします。

//custom validatorjs / checkbox  
Validator.register('checkbox', function (value, requirement, attribute) {  
    const valArray = value.split(',');  
    for (const val of valArray) {  
        if (requirement.indexOf(val) === -1) {  
            return false;  
        }  
    }  
    return true;  
}, ':attribute は無効です。');  
//generate instance  
const validatorjs = new Validator(arrayData, rules);  
  • register メソッドでカスタムルールを登録
  • 第一引数がルール名、第二引数にバリデーションの処理、第三引数がエラーメッセージ
  • バリデーション処理の戻り値は true or false
  • エラーメッセージのプレースホルダーは :attribute

となっています。

今回は必須は標準の required に任せて、最初にカンマ区切りの文字列を配列に戻した後に、「各値( val )が想定される値の配列( requirement )に含まれるかどうか」をチェックしています。

Valitron

続いて PHP 側。

//custom valitron / checkbox  
\Valitron\Validator::addRule('checkbox', function ($field, $value, array $params, array $fields) {  
    $valArray = explode(',', $value);  
    for ($i = 0; $i < count($valArray); $i++) {  
        if (!in_array($valArray[$i], $params[0], true)) {  
            return false;  
        }  
    }  
    return true;  
}, '{field}が無効な値です。');  
//generate instance  
$v = new \Valitron\Validator($post);  
  • addRule メソッドでカスタムルールを登録
  • 第一引数がルール名、第二引数にバリデーションの処理、第三引数がエラーメッセージ
  • バリデーション処理の戻り値は true or false
  • エラーメッセージのプレースホルダーは {field}
  • バリデーション処理の引数は以下の通り
    • $field: フィールドのキー名(イメージとしては name 属性に指定された $_POST のキー)
    • $value: 入力値
    • $params: 要件。想定される値の配列

全体的な使い方は validatorjs と似ています。

やや引っかかったのは要件が配列に入っているので、アクセスの際は $params ではなく $params[0] を使うこと。

JavaScript 側と同様、必須要件は required に任せて「各値( $valArray[$i] )が想定される値の配列( $params[0] )に含まれるかどうか」のチェックに専念しています。

ちなみに、 Valitron は subset というルールが標準で存在するためこれが使えそうだと思ったのですが、思うように動かなかったのでカスタムルールを作成することにしました。

備考

今回の JavaScript での値の取得(input type="checkbox" から 文字列へ)は以下のような処理で実装しました( jQuery 使用)。

let arrayData = [];  
let strArrayCheckbox = '';  
$(`input[name="divinity[]"]:checked`).each(function (index) {  
    strArrayCheckbox += $(this).val();  
    if (index < $(`input[name="divinity[]"]:checked`).length - 1) {  
        strArrayCheckbox += ',';  
    }  
});  
arrayData['divinity'] = strArrayCheckbox;  

一応メモ。

参考

validatorjs

Valitron

技術ブログをはじめよう Qrunch(クランチ)は、プログラマの技術アプトプットに特化したブログサービスです
駆け出しエンジニアからエキスパートまで全ての方々のアウトプットを歓迎しております!
or 外部アカウントで 登録 / ログイン する
クランチについてもっと詳しく

この記事が掲載されているブログ

アルム=バンドのQrunch

よく一緒に読まれる記事

0件のコメント

ブログ開設 or ログイン してコメントを送ってみよう