Skip to content

Commit 673b16a

Browse files
committed
feat: Unify validator API and refine error reporting
This commit introduces several improvements to the validator library: - **Unified API for FieldValidator**: The now includes a method, aligning its API with . The method now calls and throws an exception on failure, ensuring consistent behavior across all validators. - **Refined Error Reporting**: Removed redundant field names from error messages. Error messages are now generic (e.g., "Value is required."), with the field context provided by the error object's key. This results in a cleaner, more structured, and easier-to-parse error output. These changes enhance the library's consistency, predictability, and overall developer experience.
1 parent 63f322f commit 673b16a

5 files changed

Lines changed: 36 additions & 11 deletions

File tree

src/Lemmon/ArrayValidator.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,12 +57,12 @@ protected function coerceValue(mixed $value): mixed
5757
protected function validateType(mixed $value, string $key): mixed
5858
{
5959
if (!is_array($value)) {
60-
throw new ValidationException([$key ? "Field '$key' must be an array." : 'Value must be an array.']);
60+
throw new ValidationException(['Value must be an array.']);
6161
}
6262

6363
// Check if it's a list (indexed array starting from 0)
6464
if (!array_is_list($value)) {
65-
throw new ValidationException([$key ? "Field '$key' must be an indexed array (list)." : 'Value must be an indexed array (list).']);
65+
throw new ValidationException(['Value must be an indexed array (list).']);
6666
}
6767

6868
// If item validator is set, validate each item

src/Lemmon/BoolValidator.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ protected function coerceValue(mixed $value): mixed
2424
protected function validateType(mixed $value, string $key): mixed
2525
{
2626
if (!is_bool($value)) {
27-
throw new ValidationException([$key ? "Field '$key' must be a boolean." : 'Value must be a boolean.']);
27+
throw new ValidationException(['Value must be a boolean.']);
2828
}
2929
return $value;
3030
}

src/Lemmon/FieldValidator.php

Lines changed: 31 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -70,24 +70,49 @@ public function oneOf(array $values): self
7070
* @throws ValidationException If validation fails.
7171
*/
7272
public function validate(mixed $value, string $key = '', array $input = []): mixed
73+
{
74+
[$valid, $data, $errors] = $this->tryValidate($value, $key, $input);
75+
if (!$valid) {
76+
throw new ValidationException($errors);
77+
}
78+
return $data;
79+
}
80+
81+
/**
82+
* Tries to validate the given value and returns a result tuple.
83+
*
84+
* @param mixed $value The value to validate.
85+
* @param string $key The key of the field being validated.
86+
* @param array<string, mixed> $input The entire input array.
87+
* @return array{bool, mixed, array<string>|null} A tuple containing:
88+
* - bool: true if validation is successful, false otherwise.
89+
* - mixed: The validated and potentially coerced value, or the original value on failure.
90+
* - array|null: An array of error messages on failure, or null on success.
91+
*/
92+
public function tryValidate(mixed $value, string $key = '', array $input = []): array
7393
{
7494
if (is_null($value)) {
7595
if ($this->hasDefault) {
76-
return $this->default;
96+
return [true, $this->default, null];
7797
}
7898
if ($this->required) {
79-
throw new ValidationException([$key ? "Field '$key' is required." : 'Value is required.']);
99+
return [false, $value, ['Value is required.']];
80100
}
81-
return null;
101+
return [true, null, null];
82102
}
83103

84104
$value = $this->coerce ? $this->coerceValue($value) : $value;
85105

86106
if ($this->oneOf && !in_array($value, $this->oneOf, true)) {
87-
throw new ValidationException([$key ? "Field '$key' must be one of: " . json_encode($this->oneOf) : 'Value must be one of: ' . json_encode($this->oneOf)]);
107+
return [false, $value, ['Value must be one of: ' . json_encode($this->oneOf)]];
88108
}
89109

90-
return $this->validateType($value, $key);
110+
try {
111+
$validatedValue = $this->validateType($value, $key);
112+
return [true, $validatedValue, null];
113+
} catch (ValidationException $e) {
114+
return [false, $value, $e->getErrors()];
115+
}
91116
}
92117

93118
/**
@@ -107,4 +132,4 @@ abstract protected function coerceValue(mixed $value): mixed;
107132
* @throws ValidationException If the type validation fails.
108133
*/
109134
abstract protected function validateType(mixed $value, string $key): mixed;
110-
}
135+
}

src/Lemmon/IntValidator.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ protected function coerceValue(mixed $value): mixed
1818
protected function validateType(mixed $value, string $key): mixed
1919
{
2020
if (!is_int($value)) {
21-
throw new ValidationException([$key ? "Field '$key' must be an integer." : 'Value must be an integer.']);
21+
throw new ValidationException(['Value must be an integer.']);
2222
}
2323
return $value;
2424
}

src/Lemmon/StringValidator.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ protected function coerceValue(mixed $value): mixed
1818
protected function validateType(mixed $value, string $key): mixed
1919
{
2020
if (!is_string($value)) {
21-
throw new ValidationException([$key ? "Field '$key' must be a string." : 'Value must be a string.']);
21+
throw new ValidationException(['Value must be a string.']);
2222
}
2323
return $value;
2424
}

0 commit comments

Comments
 (0)