Valitron
ライブラリ
Valitron
概要
Valitronは、依存関係のないシンプルで軽量なPHPバリデーションライブラリです。Vance Lucasによって開発され、読みやすく簡潔な構文でバリデーションを実行できることが特徴です。他のフレームワークの大きなコンポーネントに依存しないため、非常に軽量で効率的。一つの関数呼び出しですべてのバリデーションを実行でき、カスタムバリデーションルールの追加や国際化にも対応しています。小規模から中規模のPHPプロジェクトで手軽にバリデーション機能を導入したい場合に最適な選択肢です。
詳細
Valitron 1.4.xは2025年現在の最新版で、PHPの様々なバリデーションニーズに対応する軽量ライブラリです。required、numeric、email、date、lengthなど30以上の組み込みバリデーションルールを提供し、日常的なWebアプリケーション開発で必要な検証機能を網羅。シンプルなメソッドチェーンによる直感的なAPI設計で、学習コストを最小限に抑制しています。外部依存関係を持たないため、既存のプロジェクトへの導入が容易で、パフォーマンスへの影響も最小限。カスタムルールの追加、国際化対応、詳細なエラーメッセージカスタマイズなど、実用的な機能も充実しています。
主な特徴
- 依存関係なし: 他のフレームワークやライブラリに依存せず、軽量で高速
- シンプルな構文: 読みやすいメソッドチェーンによる直感的なバリデーション定義
- 豊富な組み込みルール: 30以上の一般的なバリデーションルールを標準搭載
- カスタムルール対応: 独自のバリデーションロジックを簡単に追加可能
- 国際化サポート: 多言語エラーメッセージとロケール固有の検証
- 軽量設計: 最小限のメモリ使用量とパフォーマンスオーバーヘッド
メリット・デメリット
メリット
- 学習コストが低く、すぐに使い始められる
- 依存関係がないため導入が簡単
- 軽量でパフォーマンスへの影響が最小限
- シンプルで読みやすいコード記述が可能
- カスタムバリデーションの実装が容易
- 小規模から中規模プロジェクトに最適
デメリット
- 複雑なバリデーションロジックには不向き
- 大規模エンタープライズ機能は限定的
- アノテーションや属性による定義は非対応
- オブジェクトのネストした検証機能が基本的
- Symfonyなどの高機能ライブラリと比較すると機能が限定的
- コミュニティとエコシステムが比較的小規模
参考ページ
書き方の例
インストールと基本セットアップ
# Composerでインストール
composer require vlucas/valitron
# 特定バージョンを指定
composer require vlucas/valitron:^1.4
基本的なバリデーション実装
<?php
require_once 'vendor/autoload.php';
use Valitron\Validator;
// シンプルなバリデーション例
$data = [
'name' => '',
'email' => 'invalid-email',
'age' => 15,
'website' => 'not-a-url'
];
$v = new Validator($data);
// バリデーションルールを定義
$v->rule('required', ['name', 'email'])
->rule('email', 'email')
->rule('integer', 'age')
->rule('min', 'age', 18)
->rule('url', 'website');
// バリデーションを実行
if ($v->validate()) {
echo "バリデーション成功!\n";
} else {
echo "バリデーションエラー:\n";
foreach ($v->errors() as $field => $messages) {
foreach ($messages as $message) {
echo "- {$field}: {$message}\n";
}
}
}
// 個別の値のバリデーション
$email = '[email protected]';
$emailValidator = new Validator(['email' => $email]);
$emailValidator->rule('required', 'email')->rule('email', 'email');
if ($emailValidator->validate()) {
echo "メールアドレスは有効です\n";
} else {
echo "無効なメールアドレス\n";
}
より詳細なバリデーション例
<?php
use Valitron\Validator;
// ユーザー登録フォームのバリデーション
$userData = [
'username' => 'user123',
'email' => '[email protected]',
'password' => 'secret123',
'password_confirm' => 'secret123',
'age' => 25,
'website' => 'https://example.com',
'phone' => '090-1234-5678',
'birthday' => '1998-05-15',
'tags' => ['php', 'web', 'development']
];
$v = new Validator($userData);
// 必須フィールド
$v->rule('required', ['username', 'email', 'password', 'password_confirm']);
// 文字列長のバリデーション
$v->rule('lengthBetween', 'username', 3, 20);
$v->rule('lengthMin', 'password', 8);
// フォーマットバリデーション
$v->rule('email', 'email');
$v->rule('url', 'website');
$v->rule('date', 'birthday');
// 数値範囲バリデーション
$v->rule('integer', 'age');
$v->rule('min', 'age', 18);
$v->rule('max', 'age', 120);
// 確認フィールドのバリデーション
$v->rule('equals', 'password_confirm', 'password');
// 正規表現バリデーション
$v->rule('regex', 'phone', '/^\d{3}-\d{4}-\d{4}$/');
$v->rule('alphaNum', 'username');
// 配列のバリデーション
$v->rule('array', 'tags');
// カスタムメッセージ
$v->message('required', '{field}は必須項目です');
$v->message('lengthMin', '{field}は{param}文字以上で入力してください');
$v->message('email', '有効なメールアドレスを入力してください');
$v->message('equals', 'パスワードが一致しません');
if ($v->validate()) {
echo "ユーザー登録データは有効です\n";
// 登録処理を実行
} else {
echo "バリデーションエラー:\n";
foreach ($v->errors() as $field => $messages) {
echo "フィールド: {$field}\n";
foreach ($messages as $message) {
echo " - {$message}\n";
}
}
}
カスタムバリデーションルールの作成
<?php
use Valitron\Validator;
// 日本の郵便番号バリデーション
Validator::addRule('japanesePostalCode', function($field, $value, $params, $fields) {
return preg_match('/^\d{3}-?\d{4}$/', $value);
}, '有効な郵便番号を入力してください(例:123-4567)');
// 強いパスワードのバリデーション
Validator::addRule('strongPassword', function($field, $value, $params, $fields) {
// 最低8文字、英大文字、英小文字、数字、特殊文字を含む
return preg_match('/^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[@$!%*?&])[A-Za-z\d@$!%*?&]{8,}$/', $value);
}, 'パスワードは8文字以上で、英大文字、英小文字、数字、特殊文字を含む必要があります');
// 日本語文字のバリデーション
Validator::addRule('japanese', function($field, $value, $params, $fields) {
return preg_match('/^[ひらがなカタカナ漢字ー]+$/u', $value);
}, '日本語で入力してください');
// 年齢制限のバリデーション(生年月日から計算)
Validator::addRule('ageRange', function($field, $value, $params, $fields) {
$birthdate = new DateTime($value);
$today = new DateTime('today');
$age = $birthdate->diff($today)->y;
$minAge = $params[0] ?? 0;
$maxAge = $params[1] ?? 120;
return $age >= $minAge && $age <= $maxAge;
}, '年齢が範囲外です');
// 重複チェック(データベース接続が必要)
Validator::addRule('unique', function($field, $value, $params, $fields) {
$table = $params[0];
$column = $params[1] ?? $field;
$excludeId = $params[2] ?? null;
// PDOなどでデータベースチェック
// これは疑似コードです
$query = "SELECT COUNT(*) FROM {$table} WHERE {$column} = ?";
if ($excludeId) {
$query .= " AND id != ?";
// $result = $pdo->prepare($query)->execute([$value, $excludeId]);
} else {
// $result = $pdo->prepare($query)->execute([$value]);
}
// 実際の実装では PDO を使用してデータベースをチェック
return true; // 疑似コードのため常にtrue
}, 'この{field}は既に使用されています');
// カスタムルールの使用例
$data = [
'postal_code' => '123-4567',
'password' => 'SecurePass123!',
'name' => 'たなか太郎',
'birthday' => '1990-05-15',
'email' => '[email protected]'
];
$v = new Validator($data);
// カスタムルールを適用
$v->rule('required', ['postal_code', 'password', 'name', 'birthday', 'email']);
$v->rule('japanesePostalCode', 'postal_code');
$v->rule('strongPassword', 'password');
$v->rule('japanese', 'name');
$v->rule('ageRange', 'birthday', 18, 65); // 18歳から65歳まで
$v->rule('email', 'email');
// $v->rule('unique', 'email', 'users', 'email'); // データベースが必要
if ($v->validate()) {
echo "すべてのカスタムバリデーションが成功しました\n";
} else {
foreach ($v->errors() as $field => $messages) {
foreach ($messages as $message) {
echo "- {$field}: {$message}\n";
}
}
}
国際化とローカライゼーション
<?php
use Valitron\Validator;
// 言語ファイルの設定
Validator::langDir(__DIR__ . '/lang'); // 言語ファイルディレクトリを設定
// 日本語に設定
Validator::lang('ja');
// カスタム言語ファイル(lang/ja.php)の例
/*
<?php
return [
'required' => '{field}は必須です',
'email' => '{field}は有効なメールアドレスではありません',
'lengthMin' => '{field}は{param}文字以上で入力してください',
'lengthMax' => '{field}は{param}文字以下で入力してください',
'lengthBetween' => '{field}は{param}文字から{param}文字の間で入力してください',
'min' => '{field}は{param}以上である必要があります',
'max' => '{field}は{param}以下である必要があります',
'integer' => '{field}は整数である必要があります',
'numeric' => '{field}は数値である必要があります',
'url' => '{field}は有効なURLではありません',
'date' => '{field}は有効な日付ではありません',
'equals' => '{field}は{param}と一致する必要があります',
'regex' => '{field}の形式が正しくありません',
'alphaNum' => '{field}は英数字のみ使用できます',
'array' => '{field}は配列である必要があります'
];
*/
// 多言語対応のバリデーション例
class MultiLangValidator
{
private $supportedLangs = ['ja', 'en'];
private $currentLang = 'ja';
public function __construct($lang = 'ja')
{
if (in_array($lang, $this->supportedLangs)) {
$this->currentLang = $lang;
Validator::lang($lang);
}
}
public function validateUserData($data)
{
$v = new Validator($data);
// フィールド名のローカライゼーション
$fieldLabels = $this->getFieldLabels();
$v->labels($fieldLabels);
// バリデーションルール
$v->rule('required', ['name', 'email', 'age']);
$v->rule('email', 'email');
$v->rule('integer', 'age');
$v->rule('min', 'age', 18);
$v->rule('lengthBetween', 'name', 2, 50);
return $v;
}
private function getFieldLabels()
{
$labels = [
'ja' => [
'name' => '名前',
'email' => 'メールアドレス',
'age' => '年齢',
'password' => 'パスワード',
'phone' => '電話番号'
],
'en' => [
'name' => 'Name',
'email' => 'Email Address',
'age' => 'Age',
'password' => 'Password',
'phone' => 'Phone Number'
]
];
return $labels[$this->currentLang] ?? $labels['ja'];
}
}
// 使用例
$userData = [
'name' => '',
'email' => 'invalid-email',
'age' => 15
];
// 日本語バリデーション
$jaValidator = new MultiLangValidator('ja');
$validator = $jaValidator->validateUserData($userData);
if (!$validator->validate()) {
echo "日本語エラーメッセージ:\n";
foreach ($validator->errors() as $field => $messages) {
foreach ($messages as $message) {
echo "- {$message}\n";
}
}
}
// 英語バリデーション
Validator::lang('en');
$enValidator = new MultiLangValidator('en');
$validator = $enValidator->validateUserData($userData);
if (!$validator->validate()) {
echo "\nEnglish error messages:\n";
foreach ($validator->errors() as $field => $messages) {
foreach ($messages as $message) {
echo "- {$message}\n";
}
}
}
高度な使用例とベストプラクティス
<?php
use Valitron\Validator;
// バリデーションクラスでの抽象化
class FormValidator
{
protected $data;
protected $validator;
protected $errors = [];
public function __construct(array $data)
{
$this->data = $data;
$this->validator = new Validator($data);
$this->setupRules();
}
protected function setupRules()
{
// サブクラスでオーバーライド
}
public function validate(): bool
{
if (!$this->validator->validate()) {
$this->errors = $this->validator->errors();
return false;
}
return $this->customValidation();
}
protected function customValidation(): bool
{
// サブクラスでカスタムバリデーションを実装
return true;
}
public function getErrors(): array
{
return $this->errors;
}
public function getFirstError(): ?string
{
foreach ($this->errors as $fieldErrors) {
return $fieldErrors[0] ?? null;
}
return null;
}
}
// ユーザー登録フォームバリデーター
class UserRegistrationValidator extends FormValidator
{
protected function setupRules()
{
$this->validator
->rule('required', ['username', 'email', 'password', 'password_confirm'])
->rule('lengthBetween', 'username', 3, 20)
->rule('alphaNum', 'username')
->rule('email', 'email')
->rule('lengthMin', 'password', 8)
->rule('equals', 'password_confirm', 'password');
// フィールドラベル
$this->validator->labels([
'username' => 'ユーザー名',
'email' => 'メールアドレス',
'password' => 'パスワード',
'password_confirm' => 'パスワード確認'
]);
}
protected function customValidation(): bool
{
// ユーザー名の重複チェック(疑似コード)
if ($this->isUsernameTaken($this->data['username'] ?? '')) {
$this->errors['username'][] = 'このユーザー名は既に使用されています';
return false;
}
// メールアドレスの重複チェック(疑似コード)
if ($this->isEmailTaken($this->data['email'] ?? '')) {
$this->errors['email'][] = 'このメールアドレスは既に使用されています';
return false;
}
return true;
}
private function isUsernameTaken(string $username): bool
{
// データベースチェックの疑似コード
return false;
}
private function isEmailTaken(string $email): bool
{
// データベースチェックの疑似コード
return false;
}
}
// プロフィール更新バリデーター
class ProfileUpdateValidator extends FormValidator
{
private $userId;
public function __construct(array $data, int $userId)
{
$this->userId = $userId;
parent::__construct($data);
}
protected function setupRules()
{
$this->validator
->rule('required', ['name', 'email'])
->rule('lengthBetween', 'name', 2, 50)
->rule('email', 'email')
->rule('url', 'website')
->rule('date', 'birthday')
->rule('lengthMax', 'bio', 500);
// オプションフィールドの条件付きバリデーション
if (!empty($this->data['password'])) {
$this->validator
->rule('lengthMin', 'password', 8)
->rule('equals', 'password_confirm', 'password');
}
}
}
// APIレスポンス用バリデーター
class ApiValidator
{
public static function validateAndRespond(FormValidator $validator): array
{
if ($validator->validate()) {
return [
'success' => true,
'message' => 'バリデーション成功',
'data' => null
];
}
return [
'success' => false,
'message' => 'バリデーションエラーが発生しました',
'errors' => $validator->getErrors(),
'first_error' => $validator->getFirstError()
];
}
}
// 使用例
$registrationData = [
'username' => 'user123',
'email' => '[email protected]',
'password' => 'password123',
'password_confirm' => 'password123'
];
$validator = new UserRegistrationValidator($registrationData);
$result = ApiValidator::validateAndRespond($validator);
if ($result['success']) {
echo "ユーザー登録バリデーション成功\n";
} else {
echo "バリデーションエラー:\n";
echo "最初のエラー: " . $result['first_error'] . "\n";
foreach ($result['errors'] as $field => $messages) {
foreach ($messages as $message) {
echo "- {$field}: {$message}\n";
}
}
}
// バッチバリデーション例
class BatchValidator
{
public static function validateMultiple(array $datasets, string $validatorClass): array
{
$results = [];
foreach ($datasets as $index => $data) {
$validator = new $validatorClass($data);
$results[$index] = [
'data' => $data,
'valid' => $validator->validate(),
'errors' => $validator->getErrors()
];
}
return $results;
}
public static function getValidData(array $results): array
{
return array_filter($results, fn($result) => $result['valid']);
}
public static function getInvalidData(array $results): array
{
return array_filter($results, fn($result) => !$result['valid']);
}
}
// CSVインポート時のバッチバリデーション例
$csvData = [
['username' => 'user1', 'email' => '[email protected]', 'password' => 'pass123456', 'password_confirm' => 'pass123456'],
['username' => 'u2', 'email' => 'invalid-email', 'password' => 'weak', 'password_confirm' => 'weak'],
['username' => 'user3', 'email' => '[email protected]', 'password' => 'strong123', 'password_confirm' => 'strong123']
];
$batchResults = BatchValidator::validateMultiple($csvData, UserRegistrationValidator::class);
$validData = BatchValidator::getValidData($batchResults);
$invalidData = BatchValidator::getInvalidData($batchResults);
echo "有効なデータ: " . count($validData) . "件\n";
echo "無効なデータ: " . count($invalidData) . "件\n";
foreach ($invalidData as $index => $result) {
echo "行 {$index}: エラーあり\n";
foreach ($result['errors'] as $field => $messages) {
foreach ($messages as $message) {
echo " - {$field}: {$message}\n";
}
}
}