ベストプラクティス
NoraLib Validationを効果的に使うための推奨事項です。
設計原則
単一責任の原則
各バリデーションルールは1つの責任のみを持つべきです:
良い例:
$validator
->notEmpty() // 空チェック
->length(min: 8) // 長さチェック
->passwordStrength(); // 強度チェック
悪い例:
// 1つのカスタムルールで全てをチェック(保守性が低い)
$validator->custom(function($value) {
return !empty($value) &&
strlen($value) >= 8 &&
preg_match('/[A-Z]/', $value) &&
preg_match('/[0-9]/', $value);
}, '複雑なエラーメッセージ');
再利用可能なポリシー
よく使うバリデーションはポリシーとして定義します:
class ValidationPolicies
{
public static function setupStandardPolicies(Validator $validator): void
{
// メールアドレス
$validator->setPolicy('email', [
new NotEmptyRule(),
new ValidEmailRule(),
]);
// 強力なパスワード
$validator->setPolicy('strong_password', [
new NotEmptyRule(),
new LengthRule(12, 64),
new PasswordComplexityRule(4),
new PasswordNoCommonWordRule(),
]);
}
}
// 使用
$validator = new Validator();
ValidationPolicies::setupStandardPolicies($validator);
$passwordValidator = $validator->policy('strong_password');
エラーハンドリング
フォーム全体のバリデーション
use NoraLib\Validation\Exception\ValidationalError;
use NoraLib\Validation\Rule\Exception\ExceptionGroup;
function validateUserForm(array $data): array
{
$validator = new Validator();
$formValidator = $validator->array([
'username' => $validator->policy('username'),
'email' => $validator->policy('email'),
'password' => $validator->policy('strong_password'),
]);
try {
$formValidator->assert($data);
return ['success' => true];
} catch (ExceptionGroup $e) {
$error = ValidationalError::createFromValidator($e);
return [
'success' => false,
'errors' => $error->buildPayload(),
];
}
}
パフォーマンス
早期リターン
バリデーションは短絡評価されます。最も失敗しやすいルールを先に配置します:
// 良い例:空チェックを最初に
$validator
->notEmpty() // 最も失敗しやすい
->length(min: 8)
->passwordStrength(); // 最も重い処理
セキュリティ
パスワードバリデーション
常に複数の側面をチェックします:
$validator->setPolicy('secure_password', [
new NotEmptyRule(),
new LengthRule(12, 128), // 最小12文字
new PasswordComplexityRule(4), // 全4種類の文字
new PasswordNoCommonWordRule(), // 一般的なパスワードを除外
]);
入力サニタイゼーション
バリデーションは検証のみを行います。サニタイゼーションは別途行ってください:
// 良い例
$cleanEmail = filter_var($email, FILTER_SANITIZE_EMAIL);
if ($validator->validEmail()->validate($cleanEmail)) {
// 使用
}
テスト
バリデーションルールのテスト
use PHPUnit\Framework\TestCase;
class CustomRuleTest extends TestCase
{
public function testEvenNumberValidation(): void
{
$rule = new EvenNumberRule();
$this->assertTrue($rule->validate(2));
$this->assertTrue($rule->validate(100));
$this->assertFalse($rule->validate(1));
$this->assertFalse($rule->validate(99));
$this->assertTrue($rule->validate(null)); // 空は許可
}
public function testEvenNumberException(): void
{
$rule = new EvenNumberRule();
$this->expectException(EvenNumberException::class);
$rule->assert(3);
}
}
まとめ
- 単一責任 : 1ルール1責任
- ポリシー : 再利用可能な組み合わせを定義
- 早期リターン : 失敗しやすいルールを先に
- セキュリティ : 複数のチェックを組み合わせる
- テスト : カスタムルールは必ずテストする