mirror of
https://github.com/vlucas/valitron.git
synced 2025-12-31 07:01:54 +00:00
Validator::rule now supports closures
Validator::rule now allows the rule to be a closure.
This allows us to add an anonymous rule that is only
valid for the specified field(s):
$someObject = new MyObject();
$v->rule(function($field, $value) use ($someObject)
return $value === $someObject->someState();
}, ["shared_secret", "other"])
->label("invalid state!");
This is especially useful if you have either a) have
a rule which you are not likely to be reusing or b)
you need access to some object which cannot be easily
connstructed (because it requires IO access, etc).
Either way, this is really only convenience method
because it saves you a call to Validator::addInstanceRule.
Internally, it does exactly that: it 1) determines a valid
rule name, 2) calls addInstanceRule() with the name
determined in 1) and the Closure, and then 3) replaces
the $rule parameter (which is the Closure object) by
the name of the rule.
1) is determined like this: if multiple parameters were
given, they are joined together into one string glued
with a underscore. '_rule' is then appended so that
the name becomes all_params_rule. If the name is already
used by any other rule, it will append up to 5
pseudo-random digits to the rule. In the unlikely event
that this rule is also used, step 1) will be repeated
until a unique rule name is found.
This commit is contained in:
parent
df78fe188c
commit
7a5fd66990
@ -1019,7 +1019,7 @@ class Validator
|
|||||||
* @param string $message
|
* @param string $message
|
||||||
* @throws \InvalidArgumentException
|
* @throws \InvalidArgumentException
|
||||||
*/
|
*/
|
||||||
public function addInstanceRule($name, $callback, $message = self::ERROR_DEFAULT)
|
public function addInstanceRule($name, $callback, $message = null)
|
||||||
{
|
{
|
||||||
static::assertRuleCallback($callback);
|
static::assertRuleCallback($callback);
|
||||||
|
|
||||||
@ -1035,24 +1035,63 @@ class Validator
|
|||||||
* @param string $message
|
* @param string $message
|
||||||
* @throws \InvalidArgumentException
|
* @throws \InvalidArgumentException
|
||||||
*/
|
*/
|
||||||
public static function addRule($name, $callback, $message = self::ERROR_DEFAULT)
|
public static function addRule($name, $callback, $message = null)
|
||||||
{
|
{
|
||||||
|
if ($message === null)
|
||||||
|
{
|
||||||
|
$message = static::ERROR_DEFAULT;
|
||||||
|
}
|
||||||
|
|
||||||
static::assertRuleCallback($callback);
|
static::assertRuleCallback($callback);
|
||||||
|
|
||||||
static::$_rules[$name] = $callback;
|
static::$_rules[$name] = $callback;
|
||||||
static::$_ruleMessages[$name] = $message;
|
static::$_ruleMessages[$name] = $message;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getUniqueRuleName($fields)
|
||||||
|
{
|
||||||
|
if (is_array($fields))
|
||||||
|
{
|
||||||
|
$fields = implode("_", $fields);
|
||||||
|
}
|
||||||
|
|
||||||
|
$orgName = "{$fields}_rule";
|
||||||
|
$name = $orgName;
|
||||||
|
$rules = $this->getRules();
|
||||||
|
while (isset($rules[$name]))
|
||||||
|
{
|
||||||
|
$name = $orgName . "_" . rand(0, 10000);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $name;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convenience method to add a single validation rule
|
* Convenience method to add a single validation rule
|
||||||
*
|
*
|
||||||
* @param string $rule
|
* @param string|callback $rule
|
||||||
* @param array $fields
|
* @param array $fields
|
||||||
* @return $this
|
* @return $this
|
||||||
* @throws \InvalidArgumentException
|
* @throws \InvalidArgumentException
|
||||||
*/
|
*/
|
||||||
public function rule($rule, $fields)
|
public function rule($rule, $fields)
|
||||||
{
|
{
|
||||||
|
// Get any other arguments passed to function
|
||||||
|
$params = array_slice(func_get_args(), 2);
|
||||||
|
|
||||||
|
// Note: we cannot use is_callable here since max, int, and many
|
||||||
|
// other string can also be callables but aren't really rule callbacks.
|
||||||
|
//
|
||||||
|
// If a closure is used, we can be sure that the user actually
|
||||||
|
// wants $rule to be a custom rule check.
|
||||||
|
if (is_object($rule) && ($rule instanceof \Closure))
|
||||||
|
{
|
||||||
|
$name = $this->getUniqueRuleName($fields);
|
||||||
|
$msg = isset($params[0]) ? $params[0] : null;
|
||||||
|
$this->addInstanceRule($name, $rule, $msg);
|
||||||
|
$rule = $name;
|
||||||
|
}
|
||||||
|
|
||||||
$errors = $this->getRules();
|
$errors = $this->getRules();
|
||||||
if (!isset($errors[$rule])) {
|
if (!isset($errors[$rule])) {
|
||||||
$ruleMethod = 'validate' . ucfirst($rule);
|
$ruleMethod = 'validate' . ucfirst($rule);
|
||||||
@ -1065,9 +1104,6 @@ class Validator
|
|||||||
$msgs = $this->getRuleMessages();
|
$msgs = $this->getRuleMessages();
|
||||||
$message = isset($msgs[$rule]) ? $msgs[$rule] : self::ERROR_DEFAULT;
|
$message = isset($msgs[$rule]) ? $msgs[$rule] : self::ERROR_DEFAULT;
|
||||||
|
|
||||||
// Get any other arguments passed to function
|
|
||||||
$params = array_slice(func_get_args(), 2);
|
|
||||||
|
|
||||||
$this->_validations[] = array(
|
$this->_validations[] = array(
|
||||||
'rule' => $rule,
|
'rule' => $rule,
|
||||||
'fields' => (array) $fields,
|
'fields' => (array) $fields,
|
||||||
|
|||||||
@ -39,7 +39,6 @@ class ValidateAddInstanceRuleTest extends BaseTestCase
|
|||||||
$v->rule("fuzzerRule", "fuzz");
|
$v->rule("fuzzerRule", "fuzz");
|
||||||
$v->rule("fooRule", "foo");
|
$v->rule("fooRule", "foo");
|
||||||
|
|
||||||
|
|
||||||
$this->assertValid($v);
|
$this->assertValid($v);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -53,4 +52,50 @@ class ValidateAddInstanceRuleTest extends BaseTestCase
|
|||||||
$v->rule("fooRule", "foo");
|
$v->rule("fooRule", "foo");
|
||||||
$this->assertFalse($v->validate());
|
$this->assertFalse($v->validate());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testAddAddRuleWithCallback()
|
||||||
|
{
|
||||||
|
$v = new Validator(array("foo" => "bar"));
|
||||||
|
$v->rule(function($field, $value) {
|
||||||
|
return $field === "foo" && $value === "bar";
|
||||||
|
}, "foo");
|
||||||
|
|
||||||
|
$this->assertValid($v);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testAddAddRuleWithCallbackFail()
|
||||||
|
{
|
||||||
|
$v = new Validator(array("foo" => "baz"));
|
||||||
|
$v->rule(function($field, $value) {
|
||||||
|
return $field === "foo" && $value === "bar";
|
||||||
|
}, "foo");
|
||||||
|
|
||||||
|
$this->assertFalse($v->validate());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testAddAddRuleWithCallbackFailMessage()
|
||||||
|
{
|
||||||
|
$v = new Validator(array("foo" => "baz"));
|
||||||
|
$v->rule(function($field, $value) {
|
||||||
|
return $field === "foo" && $value === "bar";
|
||||||
|
}, "foo", "test error message");
|
||||||
|
|
||||||
|
$this->assertFalse($v->validate());
|
||||||
|
$errors = $v->errors();
|
||||||
|
$this->assertArrayHasKey("foo", $errors);
|
||||||
|
$this->assertCount(1, $errors["foo"]);
|
||||||
|
$this->assertEquals("Foo test error message", $errors["foo"][0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testUniqueRuleName()
|
||||||
|
{
|
||||||
|
$v = new Validator(array());
|
||||||
|
$args = array("foo", "bar");
|
||||||
|
$this->assertEquals("foo_bar_rule", $v->getUniqueRuleName($args));
|
||||||
|
$this->assertEquals("foo_rule", $v->getUniqueRuleName("foo"));
|
||||||
|
|
||||||
|
$v->addInstanceRule("foo_rule", function() {});
|
||||||
|
$u = $v->getUniqueRuleName("foo");
|
||||||
|
$this->assertRegExp("/^foo_rule_[0-9]{1,5}$/", $u);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user