feat(validation): Add human-readable validation error messages
This commit is contained in:
@@ -84,11 +84,11 @@ class Request extends Neuron
|
||||
return true;
|
||||
}
|
||||
|
||||
if (isset(static::messages()[Validator::$lastFailed])) {
|
||||
$error = static::messages()[Validator::$lastFailed];
|
||||
} else {
|
||||
$error = 'Error: validation failed of ' . preg_replace('/\./', ' as ', Validator::$lastFailed, 1);
|
||||
}
|
||||
$error = Validator::message(
|
||||
Validator::$lastFailed,
|
||||
static::messages(),
|
||||
static::attributes()
|
||||
);
|
||||
|
||||
static::onInvalid($error);
|
||||
return false;
|
||||
@@ -134,6 +134,19 @@ class Request extends Neuron
|
||||
return [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Human-readable names for the fields.
|
||||
*
|
||||
* Forwarded to Validator::message() so the :attribute marker in the error
|
||||
* text can be replaced with a friendlier name (e.g. "edad" => "la edad").
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function attributes(): array
|
||||
{
|
||||
return [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Function to execute when an invalid value has been detected.
|
||||
*
|
||||
|
||||
@@ -52,6 +52,123 @@ class Validator
|
||||
*/
|
||||
private const DATA_AWARE_RULES = ['confirmed', 'required_with', 'required_if'];
|
||||
|
||||
/**
|
||||
* Default error message template for each rule, used by message() to build
|
||||
* the text for the first failing rule.
|
||||
*
|
||||
* Supported placeholders:
|
||||
* |------------+--------------------------------------------------|
|
||||
* | Marker | Replaced with |
|
||||
* |------------+--------------------------------------------------|
|
||||
* | :attribute | attributes[campo] if given, else the field name |
|
||||
* | :min | the min/between lower bound |
|
||||
* | :max | the max/between upper bound |
|
||||
* | :size | the size rule value |
|
||||
* | :value | the required_if expected value |
|
||||
* | :other | the required_if companion field / confirmation |
|
||||
* | :values | a comma list (enum, mimes, required_with) |
|
||||
* |----------+----------------------------------------------------|
|
||||
*
|
||||
* @var array<string,string>
|
||||
*/
|
||||
public static array $messageTemplates = [
|
||||
'not' => 'The :attribute is not valid.',
|
||||
'exists' => 'The :attribute field is missing.',
|
||||
'required' => 'The :attribute field is required.',
|
||||
'number' => 'The :attribute must be a number.',
|
||||
'int' => 'The :attribute must be an integer.',
|
||||
'float' => 'The :attribute must be a float.',
|
||||
'bool' => 'The :attribute must be a boolean.',
|
||||
'string' => 'The :attribute must be a string.',
|
||||
'array' => 'The :attribute must be an array.',
|
||||
'email' => 'The :attribute must be a valid email address.',
|
||||
'url' => 'The :attribute must be a valid URL.',
|
||||
'enum' => 'The selected :attribute is invalid. Allowed: :values.',
|
||||
'min' => 'The :attribute must be at least :min.',
|
||||
'max' => 'The :attribute must not be greater than :max.',
|
||||
'between' => 'The :attribute must be between :min and :max.',
|
||||
'size' => 'The :attribute must be exactly :size.',
|
||||
'regex' => 'The :attribute format is invalid.',
|
||||
'date' => 'The :attribute is not a valid date.',
|
||||
'confirmed' => 'The :attribute confirmation does not match.',
|
||||
'required_with' => 'The :attribute field is required when :values is present.',
|
||||
'required_if' => 'The :attribute field is required when :other is :value.',
|
||||
'nullable' => 'The :attribute field may be null.',
|
||||
'file' => 'The :attribute must be a file.',
|
||||
'image' => 'The :attribute must be an image.',
|
||||
'mimes' => 'The :attribute must be a file of type: :values.',
|
||||
];
|
||||
|
||||
/**
|
||||
* Builds the human-readable message for a single failed validation.
|
||||
*
|
||||
* Pure helper: it only reads its arguments and never reads nor writes
|
||||
* $lastFailed or any other state, and it is independent of Request. A
|
||||
* controller may adopt it (opt-in) to render a message with :attribute in
|
||||
* place of Request's default text.
|
||||
*
|
||||
* Resolution order for the message text:
|
||||
* 1. $messages[$lastFailed] override by full "field.rule:args"
|
||||
* 2. $messages["field.rule"] override by "field.rule" (no args)
|
||||
* 3. $messageTemplates[rule] default for the rule
|
||||
* Placeholders are then substituted in whichever text was chosen.
|
||||
*
|
||||
* @param string $lastFailed The "field.rule[:args]" produced by validateList().
|
||||
* @param array $messages Optional per-field overrides.
|
||||
* @param array $attributes Optional human field names ("field" => "Field").
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function message(string $lastFailed, array $messages = [], array $attributes = []): string
|
||||
{
|
||||
$separator = strpos($lastFailed, '.');
|
||||
|
||||
if ($separator === false) {
|
||||
return 'The :attribute is invalid.';
|
||||
}
|
||||
|
||||
$target = substr($lastFailed, 0, $separator);
|
||||
$ruleStr = substr($lastFailed, $separator + 1);
|
||||
[$rule, $rawArguments] = static::parseRule($ruleStr);
|
||||
|
||||
$text = $messages[$lastFailed]
|
||||
?? $messages[$target . '.' . $rule]
|
||||
?? (static::$messageTemplates[$rule] ?? 'The :attribute is invalid.');
|
||||
|
||||
$replace = [
|
||||
':attribute' => $attributes[$target] ?? $target,
|
||||
];
|
||||
|
||||
$args = static::splitArguments($rule, $rawArguments);
|
||||
|
||||
switch ($rule) {
|
||||
case 'min':
|
||||
$replace[':min'] = $args[0] ?? '';
|
||||
break;
|
||||
case 'max':
|
||||
$replace[':max'] = $args[0] ?? '';
|
||||
break;
|
||||
case 'between':
|
||||
$replace[':min'] = $args[0] ?? '';
|
||||
$replace[':max'] = $args[1] ?? '';
|
||||
break;
|
||||
case 'size':
|
||||
$replace[':size'] = $args[0] ?? '';
|
||||
break;
|
||||
case 'enum':
|
||||
case 'mimes':
|
||||
case 'required_with':
|
||||
$replace[':values'] = implode(', ', $args);
|
||||
break;
|
||||
case 'required_if':
|
||||
$replace[':other'] = $args[0] ?? '';
|
||||
$replace[':value'] = $args[1] ?? '';
|
||||
break;
|
||||
}
|
||||
|
||||
return strtr($text, $replace);
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates a list of rules against the properties of an object.
|
||||
*
|
||||
|
||||
Reference in New Issue
Block a user