Today i needed to validate some input from a form before passing it into MongoDB in Lithium and found a shortcoming in the inbuilt validation system. It does not support array of values.
Consider the following simple validation rule on a string input that works for blocking empty string for appearing in your database:
<?php
class Bar extends \lithium\data\Model
{
public $validates = array(
'foo' => array(
array(
'notEmpty',
'message' => 'Must have foo',
),
),
);
}
Try passing an array to “foo” and it fails nicely. After filing a ticket for this kind of feature and discussed it on the IRC channel, I sat down and created a middleground solution by building my own validator that reused the inbuilt validator patterns for strings, only supporting array usage. Check this out:
<?php
Validator::add('array', function(&$value, $format = null, array $options = array()) {
$options += array(
'threshold' => 0,
'validator' => 'notEmpty'
);
if (is_array($value)) {
$failed = 0;
$valueCount = count($value);
foreach ($value as $item) {
if (is_string($item) && !Validator::rule($options['validator'], $item))
$failed++;
}
/**
* Threshold meanings:
* 0 = Ever set value must validate
* +x = At least x values must validate
* -x = At max x values can fail
*/
if ($options['threshold'] == 0)
return $failed == 0;
elseif ($options['threshold'] < 0)
return ($failed <= abs($options['threshold']));
else
return (($valueCount - $failed) >= $options['threshold']);
}
elseif (is_string($value))
return Validator::rule($options['validator'], $value);
return true;
});
class Bar extends \lithium\data\Model
{
public $validates = array(
'foo' => array(
array(
'array',
'validator' => 'notEmpty',
'message' => 'Must have foo',
'threshold' => 1 // Need at least on
),
),
);
}
I hope we can see this functionality in Lithium itself, but for now this little validator allows you to reuse any (not tested on all) validations found in Validator. Enjoy