Laravel has a nice validation framework, but a big catch is that it doesn't make sure your result has the right types.
here an example:
$data = ['isOk' => '1'];
$result = $this->validate($data, ['isOk' => 'boolean');
$isOkString = $result['isOk'];
$isOkBoolean = (boo;) $result['isOk'];
if($isOkString === true){
// wont fall here.
}
if($isOkBoolean === true){
// but will go here.
}
wouldn't be wonderful to make sure you have no side affects.
Todo this we must create a nice interface to be able to make Rules allow to transform the result. You must subclass the Laravel Validator
and extend the method: validateUsingCustomRule
interface RuleTransformsResult
{
public function transformResult($attribute, $value);
}
class MyTypeSafeValidator extends \Illuminate\Validation\Validator {
protected function validateUsingCustomRule($attribute, $value, $rule)
{
// below is just copy pasted laravel code of method
if (!$rule->passes($attribute, $value)) {
$this->failedRules[$attribute][get_class($rule)] = [];
$messages = (array) $rule->message();
foreach ($messages as $message) {
$this->messages->add($attribute, $this->makeReplacements(
$message, $attribute, get_class($rule), []
));
}
// here is where we do our magic
} elseif ($rule instanceof RuleTransformsResult) {
$newValue = $rule->transformResult($attribute, $value, $result);
if($newValue !== $value) {
Arr::set($this->data, $attribute, $result);
}
}
}
}
Now we can write our own Boolean validator:
class ValidBoolean implements Rule, RuleTransformsResult
{
public static $validValuesMap = [
'0' => false,
'1' => true,
'false' => false,
'true' => true,
'yes' => true,
'no' => false,
];
public function passes($attribute, $value)
{
if (is_bool($value)) {
return true;
}
return array_key_exists((string) $value, self::$validValuesMap);
}
public function message()
{
return __('validation.boolean');
}
public function transformResult($attribute, $value)
{
return (bool) $value;
}
}
Now we can always have a boolean as result:
$data = ['isOk' => '1'];
$result = $this->validate($data, ['isOk' => [new ValidBoolean()]);
if($result['isOk'] === true){
// yeah we will make it here.
}
Top comments (0)