Validator::Custom 1.0 以前におけるドキュメント

このページはValidator::Custom 1.0 以前のドキュメントになります。最新版のドキュメントは、こちらです。


 Validator::CustomHTMLフォームのデータのバリデーション(値の検証)を行うための便利なモジュールです。バリデーションのルールを少ない記述で書けること、制約ごとにエラーメッセージを設定できること、良く使う機能は最初から提供していて、ユーザー定義の制約を簡単に追加できる柔軟性の高い設計などが特徴です。

use Validator::Custom;
my $vc = Validator::Custom->new;

# データ
my $data = {
  price => 1200
  name => 'Perl',
  password => 'secret',
  passwrod2 => 'secret'
};

# ルールの作成
my $rule = $vc->create_rule($data, $rule);
$rule->require('price')->check('int')->message('price must be number');

$rule->optional('name')
  ->check('not_blank')->message('name is empty')
  ->check({length => [0, 20])->message('name is too long');

$rule->require('password')
  ->check('not_blank')->message('password is empty')
  ->check('ascii')->message('password contains invalid caharcters');

$rule->require(['password', 'password2'])->name('password_check')
  ->check('duplication')->message('Two password not match')
  ->copy(0);

# バリデーション
my $vresult = $vc->validate($data, $rule);

# 結果の確認
if ($vresult->is_ok) {
  # 安全なデータ
  my $safe_data = $vresult->data;
}
else {
  # エラーメッセージ
  my $errors = $vresult->messages;
}

 ルール作成の古い文法はこちら。上記の新しい文法で書くのが推奨です。

# ルールの作成(古い文法)
my $rule = [
  price => [
    [int => 'price must be number']
  ],
  name => [
    [not_blank => 'name is empty'],
    [{length => [0, 20]} => 'name is too long']
  ],
  password => [
    [not_blank => 'password is empty'],
    [ascii => 'password contains invalid caharcters']
  ],
  {password_check => ['password', 'password2']}
    => {copy => 0}
    => [
      [duplication => 'Two password not match']
    ]
];

 こちらのドキュメントは、新しい文法に書き直しますので、古い文法については、公式のドキュメントを参考にしてください。

Validator::Customのインストール

 Validator::Customインストールするにはcpanコマンドを使用します。

cpan Validator::Custom

 WindowsでもUnix系のOSでもインストールすることができます。cpanコマンドではルート権限がないインストールを行うことができませんので、ユーザーのローカル環境にインストールしたい場合はcpanmなどのツールを使用してください。

Validator::Customオブジェクトの生成

 Validator::Customオブジェクトの生成するにはnewメソッドを使用します。

use Validator::Custom;
my $vc = Validator::Custom->new;

 このオブジェクトを使ってバリデーションの処理を行います。

バリデーションの基礎

 バリデーションの基礎について解説します。以下のソースコードを見てください。

use Validator::Custom;
my $vc = Validator::Custom->new;

# データ
my $data = {price => 1200};

# ルールの作成
my $rule = $vc->create_rule;
$rule->require('price')->check('int');

# バリデーション
my $vresult = $vc->validate($data, $rule);

# 結果の確認
if ($vresult->is_ok) { print "OK\n" }
else { print "Not OK\n" }
データ

 バリデーションを行うデータは、ハッシュリファレンスである必要があります。

# データ
my $data = {price => 1200};
ルール

 次にバリデーションのためのルールを作成します。

# ルール
my $rule = $vc->create_rule;
$rule->require('price')->check('int');

 まず最初にValidator::Custom::Ruleオブジェクトを、create_ruleメソッドを使って、作成します。

my $rule = $vc->create_rule;

 次に、requireメソッドを使って、存在する必要のあるキーの名前を記述します。

$rule->require('price')

 もしキーが任意のものであるならば、requireの代わりにoptionalを使うこともできます。

$rule->optional('price')

 次に制約を記述します。

$rule->require('price')->check('int');

 今回はひとつのキーのチェックだけですが、複数の値をチェックする場合は、引き続き記述していくことができます。

$rule->require('name')->check('string');
バリデーション

 バリデーションを行うには、validateメソッドを使用します。

# バリデーション
my $vresult = $vc->validate($data, $rule);

 戻り値は、Validator::Custom::Resultオブジェクトです。

結果の確認

 Validator::Custom::Resultオブジェクトを使って、結果の確認を行うことができます。

my $ok = $vresult->is_ok;

 is_okメソッドで、バリデーションの結果が正しいかどうかを確認することができます。

複数の値のバリデーション

 複数の値のバリデーションを行うためのルールを作成してみます。

# 複数の値を含むデータ
my $data = {price => 1200, title => 'Perl'};

# 複数の値のバリデーションを行うためのルール
my $rule = $vc->create_rule;
$rule->require('price')->check('int');
$rule->require('title')->check('ascii');

 複数の値をバリデーションのするときは、次のように複数回requireを書くだけです。ルールの中身は次のようになります。

my $rule = $vc->create_rule;
$rule->require('price')->check('int');
$rule->require('title')->check('ascii');

ユーザー定義の制約の登録 - register_constraint

 デフォルトで用意されている制約とand条件とor条件を使って、さまざまな制約を表現することができました。Validator::Customではこれに加えて、ユーザー定義の制約を新しく登録することができます。

 ここでは簡易的に、Emailが正しい形式であるかを確認するための制約を登録してみます。制約を登録するにはregister_constraintメソッドを使用します。

# Emailが正しい形式かを確認するための制約を登録
$vc->register_constraint(
  email => sub {
    my $value = shift;
    
    # 正しいときは1を、正しくないときは0を返却
    return 0 unless defined $value;
    return $value =~ /^.+@.+$/ ? 1 : 0;
  }
);

 制約の登録の形式は次のようになります。

$vc->register_constraint(
  制約名 => 制約のための処理
);

 一度に複数の制約を登録することもできます。

$vc->register_constraint(
  制約名1 => 制約のための処理1,
  制約名2 => 制約のための処理2
);

 制約のための処理は、サブルーチンのリファレンスです。データが正しいときは1を、正しくないときは0を返すようにしてください。

sub 約名 {
  ...  
  if(正しい) {
    return 1;
  }
  else {
    return 0;
  }
}

 登録した制約は、ルールの中で利用することができます。

# 複数の値のバリデーションを行うためのルール
my $rule = $vc->create_rule;
$rule->require('admin_email')->check('email');
my $data = {admin_email => 'foo@my.com'};

制約関数を登録する

 Validator::Customでは、バリデーションのための制約関数を簡単に登録することができます。制約関数を登録するにはregister_constraintメソッドを使用します。

$vc->register_constraint(
  tel_num => sub {
    my $value = shift;
    $value =~ /^[\d-]+$/ ? 1 : 0;
  }
);

 値が正しいものであった場合は1を、値が間違ったものであった場合は0を返却するようにします。注意として、真になる値として、配列のリファレンスを返却してはいけません。配列のリファレンスは制約関数をフィルタとして扱う場合に利用されるからです。

 このように登録した制約関数はルールの中で使用することができます。

$rule->require('tel')->check('tel_num');

 制約関数は複数同時に登録することもできます。

$vc->register_constraint(
  tel_num => sub {
     my $value = shift;
     $value =~ /^[\d-]+$/ ? 1 : 0;
  },
  hiragana => sub { ... }
);

項目が存在しなくてもよい require => 0 / Validator::Customリファレンス

 項目が存在しても存在しなくてもよい場合はrequireメソッドの代わりにoptionalメソッドを使用します。

my $rule = $vc->create_rule;
$rule->optional('name')->check('int');

 上記のルールはnameが存在しても存在しなくてもよくて、存在する場合はintでなければならないことを表現します。

少なくともひとつの項目に値が含まれている

 複数のテキストボックスを入力して、そのうちの少なくともひとつに値が含まれていることをチェックしたい場合があります。このような場合は少し工夫がいります。テキストボックスの値をマージしてから、それが空でないことをチェックするのがよいでしょう。

# 少なくともひとつの項目に値が含まれている
my $vc = Validator::Custom->new;
$data = {name1 => 'Ken', name2 => '', name3 => 'Taro'};
$rule = [
  {key => qr/^name\d+$/} => [
    'merge',
    'trim',
    'not_blank'
  ],
];
my $result = $vc->validate($data, $rule);

and条件を使ったルール

このページはVersion 0.xxに関するドキュメントになります。最新版のドキュメントは、こちらです。


 バリデーションを行うときに、複数の条件を満たしているかどうかを記述したいことがあります。たとえば、1000より大きくて2000より小さいという条件を書きたいときなどです。

 and条件を使ったルールを作成してみます。checkメソッドを複数回呼び出すだけです。ここではgreater_thanとless_thanという制約を使っています。ハッシュリファレンスで制約を指定することで、引数を渡すこともができます。

# データ
my $data = {price => 1200};

# and条件を使ったルール
my $rule = $vc->create_rule;
$rule->require('price')
  ->check({greater_than => 1000})
  ->check({less_than => 2000});

or条件を使ったルール

 バリデーションを行うときに、あるひとつの条件を満たしているかどうかを記述したいことがあります。たとえば、空白あるいは整数という条件を記述したい場合があります。

 or条件を使ったルールを作成してみます。or条件を記述するにはcheck_orメソッドを使用します。

# データ
my $data = {price => 1200};

# or条件を使ったルール
my $rule = $vc->create_rule;
$rule->require('price')->check_or('blank', 'int');
and条件とor条件を同時に使う

 and条件とor条件を同時に使うこともできます。

$rule->require('price')
  ->check_or('blank', 'int')
  ->check({greater_than => 1000});

制約での引数の指定

 デフォルトで用意されている制約には引数を受け取ることができるものがあります。equal_to, betweenなどです。

 引数を渡すには制約名の部分をハッシュリファレンスを使って次のように指定します。

{制約名 => 引数}

 equal_tobetweenのサンプルは次のようになります。

my $rule = $vc->create_rule;
$rule->require('price')->check({'equal_to' => 1000});
$rule->require('age')->check({between => [1, 20]});
my $data = {price => 1000, age => 19};

 引数には、スカラ値であれば、文字列でも数値でも、配列のリファレンスでも、ハッシュのリファレンスでも渡すことができます。

to_array(フィルタ) - 配列のリファレンスへの変換

 値を配列のリファレンスに変換したい場合はto_arrayフィルタを使用します。

# データ
my $data = {languages => 'Japanese'};

# ルール
my $rule = $vc->create_rule;
$rule->require('languages')->filter('to_array');

my $vresult = $vc->validate($data, $rule);
print $vresult->data->{languages}; # ['Japanese']

 to_arrayは配列のリファレンスではないデータを配列のリファレンスに変換します。もともと配列のリファレンスだった場合は何もしません。

 これはチェックボックスなどで、ひとつの値がくるか、複数の値がくるかがわからない場合に、配列のリファレンスに変換するのに便利です。

in_array(制約関数) - 値が配列の値に含まれたものがどうかをチェックする

 HTMLフォームのチェックで、値が、ある値以外は許可したくないという場合があると思います。そのような場合はin_array制約関数を使用します。

# データ
my $data = {food => 'sushi'};

# ルール
my $rule = $rule->create_rule;
$rule->require('food')->check({'in_array' => [qw/sushi bread apple/]});

 in_array制約関数の引数には、許容する値を含んだ配列のリファレンスを指定します。

{'in_array' => [qw/sushi bread apple/]}
チェックボックスなどの複数の値に適用する

 チェックボックスの値は、複数になりますね。複数の値すべてが、ある値に含まれてほしいという場合は次のように記述します。

# 複数の値
my $data = {food => ['sushi', 'cake']};

# ルール
my $rule = $vc->create_rule;
$rule->require('food')
  ->each(1)->check({'in_array' => [qw/sushi bread apple/]);

my $is_valid = $vc->validate($data, $rule);

 eachメソッドを利用することで、要素のそれぞれの値に対して、検証を行うことができます。

 少しややこしいですが、覚えてしまうと便利です。

応用

 たとえば、少なくともひとつがチェックされていて、そのすべての値が001か002というルールは次のようにかけます。

# ルール
$rule->require('food')
  ->filter('to_array')
  ->check('selected_at_least')
  ->each(1)
  ->check({'in_array' => [qw/001 002/]});

 Validator::Customを使うと、HTMLフォームのバリデーションチェックが簡単にかけます。

selected_at_least(制約関数) - 少なくともひとつが選択されている

 HTMLフォームで、チェックボックスの中で、少なくともひとつが選択されているかを調べたい場合があります。そのようなときはselected_at_least制約関数を使用します。

# データ
my $data = {hobby => ['music', 'movie' ]};

# ルール
my $rule = $vc->create_rule;
$rule->require('hobby')->check({selected_at_least => 1});

 selected_at_least制約関数には、引数で少なくともいくつ選択されている必要があるかを指定できます。このサンプルでは、1が指定されているので、少なくともひとつという意味になります。

制約関数の中で登録されている制約関数を利用する

 Validator::Customでバリデーションのための制約関数を書くときに、低レベルな制約関数を利用したいという場合があるかと思います。

 次のように書きます。

use Validator::Custom;
my $vc = Validator::Custom->new;

$vc->register_constraint(
  int_plus_alpha => sub {
    my ($value, $args, $vc) = @_;
    
    my $is_int = $vc->constraints->{'int'}->($value);
    
    my $is_valid = $is_int && $value < 1000;
    
    return $is_valid;
  }
);

 制約関数は、第3引数として、Validator::Customオブジェクトがわたってくるというのがポイントです。

 constraints属性は、制約関数を含むハッシュリファレンスを返却しますので、以下のようにしてすでに登録されている制約関数を利用することができます。

my $is_int = $vc->constraints->{'int'}->($value);

uint(制約関数) - 非負数の整数

 HTMLフォームで、非負数の整数のみを許可したい場合があると思います。そのような場合は、uint制約関数を使用します。

# データ
my $data = {age => 19};

# ルール
my $rule = $vc->create_rule;
$rule->require('age')->check('uint');

my $is_valid = $vc->validate($data, $rule);

 内部的には「^[0-9]+$」という正規表現が使われています。

duplication(制約関数) - メールアドレスが一致していることをチェック

 HTMLフォームで、パスワードを二つ入力してもらって、パスワードが同じことをチェックしたい場合があります。そのような場合は、duplication制約関数を使用します。

# データ
my $data = {mail1 => 'a@somehost.com', mail2 => 'a@somehost.com'};

# ルール
my $rule = $vc->create_rule;
$rule->require(['mail1', 'mail2'])->name('mail_check')
  ->check('duplication');

 二つの値がどちらも未定義の場合は、バリデーションは失敗することに注意してください。

length(制約関数) - 文字列の長さのチェック

 HTMLフォームで、文字列の長さをチェックしたい場合があると思います。そのような場合は、length制約関数を使用します。

# データ
my $data = {value1 => 'aaa', value2 => 'bbbbb'};

# ルール
my $rule = $vc->create_rule;
# 長さは3
$rule->require('value1')->check({'length' => 3});
# 長さが2以上5以下
$rule->require('value2')->check({'length' => [2, 5]});
# 長さが2以上
$rule->require('value3')->check({'length' => {min => 2, max => 5}});
# 長さが2以上
$rule->require('value4')->check({'length' => {min => 2, max => 5}});
# 長さが5以下
$rule->require('value4')->check({'length' => {max => 5}});

 長さのチェックができます。文字列が内部文字列の場合は文字列の長さをチェックできます。文字列がバイト文字列の場合は、バイト数をチェックします。

defined(制約関数) - 定義されている

 定義されていることを指定するにはdefined制約関数を使用します。

my $data => {name => 'Ken'};
my $rule = $vc->create_rule;
$rule->require('name')->check('defined');

 HTMLフォームの場合は、空文字列かどうかを確認できればよいのでdefineの代わりにnot_blankを使えばよいでしょう。

decimal(制約関数) - 正の数値(桁数指定)

このページはVersion 0.xxに関するドキュメントになります。最新版のドキュメントは、こちらです。


 数値であることを指定するにはdecimal制約関数を使用します。数値というのは正の整数と少数を含みます。負の数は含まないので注意してくだだい。引数で小数点の前にくる最大の桁数と小数点の後にくる最大の桁数を指定できます。

my $data = {num1 => '123', num2 => '1.45'};
my $rule = $vc->create_rule;
$rule->require('num1')->check({'decimal' => 3});
$rule->require('num2')->check({'decimal' => [1, 2]});

blank(制約関数) - 空文字列

 空文字列であることを指定するにはblank制約関数を使用します。

my $data = {name => ''};
my $rule = $vc->create_rule;
$rule->require('name')->check('blank');

 HTMLフォームのバリデーションにおいては、特に使う機会はないと思います。

between(制約関数) - AからBの間の数値

 AからBの間の数値であることを指定するにはbetween制約関数を使用します。両端のAとBを含むということに注意してください。

my $data = {age => 19};
my $rule = $vc->create_rule;
$rule->require('age')->check({between => [1, 20]});

 betweenは整数であるかどうかは考慮しません。さらに整数の制約をかけたい場合はint制約関数もあわせてしようしてください。

ascii(制約関数) - アスキー図形文字

 HTMLフォームのパスワードなどアスキーの印字文字(16進数の21〜7Eまで)のみを許可したい場合があります。そのような場合はascii制約関数を使用します。

my $data = {password => 'ajf&$#-'};
my $rule = $vc->create_rule;
$rule->require('password')->check('ascii');

 ASCIIコードの全体ではなくって、図形文字の範囲なので、タブや空白などが含まれていた場合はバリデーションが失敗します。

duplication(制約関数) - 二つの値が同一であることのチェック

 ふたつの値が一致していることをチェックしたい場合はC制約関数を使用します。どちらか一方の値が未定義だった場合は常にバリデーションは失敗します。

 複数の値

my $data = {password1 => 'secret', password2 => 'secret'};
my $rule = $vc->create_rule;
$rule->require(['passwrod1', 'password2'])->name('password_check')
  ->check('duplication');

 複数の値をチェックする場合は、配列のリファレンスをrequireメソッドに渡すことができます。この場合は、キーの値をnameメソッドをつけてください。

パスワードのチェックを実際に行う

 パスワードのチェックを実際に行う場合は、パスワードが空ではないこと、パスワードがアスキーの図形文字だけで構成されていることのチェックもあわせて行います。またふたつのパスワードが一致しているという制約については、バリデーション後の安全なデータに識別キーに対応する値は必要がないのでcopyオプションに0を指定しておきましょう。

 ルールは以下のようになります。

$rule->require('password')
  ->check('not_blank')->message('password is empty')
  ->check('ascii')->message('password contains invalid character');
$rule->require(['password1', 'password2'])->name('password_check')
  ->check('duplication')->message('Two password is not matched')

regex(制約関数) - 正規表現にマッチする

 HTMLフォームで、ある正規表現にマッチすることをチェックしたい場合はregex制約関数を使用します。

#データ
my $data = {num => '123'};

# ルール
my $rule = $vc->create_rule;
$rule->require('num')->check({'regex' => qr/\d{0,3}/});

not_space(制約関数) - 空白文字ではない

 HTMLフォームで、空白文字ではないことをチェックしたい場合はnot_space制約関数を使用します。空白文字とは空白文字、タブ文字、改行文字だけで構成されている文字列のことです。文字列が存在しない場合も含まれます。ユニコードにおける空白文字は含まれません。

#データ
my $data = {name => 'Ken'};

# ルール
my $rule = $vc->create_rule;
$rule->require('name')->check('not_space');

not_defined(制約関数) - 値が定義されていない

 HTMLフォームで、値が定義されていないことをチェックしたい場合はnot_defined制約関数を使用します。

#データ
my $data = {name => 'Ken'};

# ルール
my $rule = $vc->create_rule;
$rule->require('name')->check('not_defined');

less_than(制約関数) - 数値がある数より小さい

 HTMLフォームで、数値がある数より小さいことをチェックしたい場合はless_than制約関数を使用します。

#データ
my $data = {num => 20};

# ルール
my $rule = $vc->create_rule;
$rule->require('num')->check({'less_than' => 25});

int(制約関数) - 整数

 HTMLフォームで、整数であることをチェックしたい場合はint制約関数を使用します。

#データ
my $data = {age => 19};

# ルール
my $rule = $vc->create_rule;
$rule->require('age')->check('int');

http_url(制約関数) - HTTPあるいはHTTPSのURL

 HTMLフォームで、HTTPあるいはHTTPSのURLであることをチェックしたい場合はhttp_url制約関数を使用します。

# データ
my $data = {url => 'http://somehost.com'};

# ルール
my $rule = $vc->create_rule;
$rule->require('url')->check('http_url');

greater_than(制約関数) - ある数より大きい

 HTMLフォームで、ある数より大きいことをチェックしたい場合はgreater_than制約関数を使用します。

#データ
my $data = {price => 1000};

# ルール
my $rule = $vc->create_rule;
$rule->require('price')->check({'greater_than' => 900});

equal_to(制約関数) - 数値が等しい

 HTMLフォームで、数値が等しいことをチェックしたい場合はequal_to制約関数を使用します。

# データ
my $data = {price => 1000};

# ルール
my $rule = $vc->create_rule;
$rule->require('price')->check({'equal_to' => 1000});