<?php
class Validator {
const GREATER = [self::class, 'greater'];
const IS_TYPE = [self::class, 'isType'];
public static function all(...$rules) {
foreach ($rules as $def) {
$rule = array_shift($def);
if ($rule(...$def)) { continue; }
return false;
}
return true;
}
public static function greater($value, $compare) : bool {
return $value > $compare;
}
public static function isType($value, $type) : bool {
return gettype($value) === $type;
}
}
class Model {
const RULES = [
'foo' => [
'integer', // shorthand for [Validator::IS_TYPE, 'integer']
[Validator::GREATER, 10]
]
];
protected $foo;
public function set($name, $value) {
if ($this->isValid($name, $value)) {
$this->$name = $value;
return;
}
throw new Exception("{$name} cannot be {$value}");
}
function isValid($name, $value) : bool {
$rules = [];
foreach (self::RULES[$name] as $rule) {
// convenience: turn strings into typehints
if (is_string($rule)) {
$rules[] = [Validator::IS_TYPE, $value];
continue;
}
// ... other convenience parsing ...
// for fully defined rules, just add value arg at proper spot
array_splice($rule, 1, 0, $value);
$rules[] = $rule;
}
return Validator::ALL($rules);
}
}
$m = new Model;
$m->set('foo', 15);
var_dump($m);
$m->set('foo', 7);
preferences:
50.14 ms | 402 KiB | 5 Q