diff --git a/README.md b/README.md index fda147c..8da23b9 100644 --- a/README.md +++ b/README.md @@ -31,13 +31,13 @@ use ProgrammatorDev\YetAnotherPhpValidator\Validator; // Do this... $validator = Validator::notBlank()->greaterThanOrEqual(18); -// ...or this... +// Or this... $validator = new Validator( new Rule\NotBlank(), new Rule\GreaterThanOrEqual(18) ); -// ...and validate with these: +// Validate with these: $validator->validate(16); // returns bool: false $validator->assert(16, 'Age'); // throws exception: The "Age" value should be greater than or equal to "18", "16" given. ``` diff --git a/docs/02-usage.md b/docs/02-usage.md index 57d33a8..6cc92bc 100644 --- a/docs/02-usage.md +++ b/docs/02-usage.md @@ -3,12 +3,22 @@ - Usage - Fluent - Dependency Injection -- Validation +- Methods - assert - validate + - getRules + - addRule +- Exception Handling +- Custom Exception Messages ## Usage +This library allows you to use validate data in two different ways: +- In a fluent way, making use of magic methods. The goal is to be able to create a set of rules with minimum setup; +- In a traditional way, making use of dependency injection. You may not like the fluent approach, and prefer to work this way. + +Both should work exactly the same. + ### Fluent ```php @@ -40,18 +50,116 @@ use ProgrammatorDev\YetAnotherPhpValidator\Validator; */ function getWeatherTemperature(float $latitude, float $longitude, string $unitSystem): float { - (new Validator(new Rule\Range(-90, 90))) - ->assert($latitude, 'Latitude'); - (new Validator(new Rule\Range(-180, 180))) - ->assert($longitude, 'Longitude'); - (new Validator(new Rule\NotBlank(), new Rule\Choice(['METRIC', 'IMPERIAL']))) - ->assert($unitSystem, 'Unit System'); + (new Validator(new Rule\Range(-90, 90)))->assert($latitude, 'Latitude'); + (new Validator(new Rule\Range(-180, 180)))->assert($longitude, 'Longitude'); + (new Validator(new Rule\NotBlank(), new Rule\Choice(['METRIC', 'IMPERIAL'])))->assert($unitSystem, 'Unit System'); // ... } ``` -A `addRule` method is also available that may be useful for conditional rules: +## Methods + +### `assert` + +This method throws a `ValidationException` when a rule fails, otherwise nothing is returned. + +```php +/** + * @throws ValidationException + */ +assert(mixed $value, string $name): void; +``` + +An example on how to handle an exception: + +```php +use ProgrammatorDev\YetAnotherPhpValidator\Exception\ValidationException; +use ProgrammatorDev\YetAnotherPhpValidator\Validator; + +function getWeatherTemperature(float $latitude, float $longitude, string $unitSystem): float +{ + Validator::range(-90, 90)->assert($latitude, 'Latitude'); + Validator::range(-180, 180)->assert($longitude, 'Longitude'); + Validator::notBlank()->choice(['METRIC', 'IMPERIAL'])->assert($unitSystem, 'Unit System'); + + // ... +} + +try { + getWeatherTemperature(latitude: 100, longitude: 50, unitSystem: 'METRIC'); +} +catch (ValidationException $exception) { + echo $exception->getMessage(); // The "Latitude" value should be between "-90" and "90", "100" given. +} +``` + +> **Note** +> The example only shows one usage approach, but both Fluent and Dependency Injection usage approaches should work the same. +> Check the [Usage](#usage) section for more information. + +### `validate` + +This method always returns a `bool` when a rule fails, useful for conditions. + +```php +validate(mixed $value): bool +``` + +An example: + +```php +use ProgrammatorDev\YetAnotherPhpValidator\Validator; + +if (!Validator::range(-90, 90)->validate($latitude)) { + // Do something... +} +``` + +> **Note** +> The example only shows one usage approach, but both Fluent and Dependency Injection usage approaches should work the same. +> Check the [Usage](#usage) section for more information. + +### `getRules` + +Returns an array with the defined set of rules. + +```php +/** + * @returns RuleInterface[] + */ +getRules(): array +``` + +An example: + +```php +use ProgrammatorDev\YetAnotherPhpValidator\Rule; +use ProgrammatorDev\YetAnotherPhpValidator\Validator; + +$validator = new Validator(new Rule\GreaterThanOrEqual(0), new Rule\LessThanOrEqual(100)); + +print_r($validator->getRules()); + +// Array ( +// [0] => ProgrammatorDev\YetAnotherPhpValidator\Rule\GreaterThanOrEqual Object +// [1] => ProgrammatorDev\YetAnotherPhpValidator\Rule\LessThanOrEqual Object +// ) +``` + +> **Note** +> The example only shows one usage approach, but both Fluent and Dependency Injection usage approaches should work the same. +> Check the [Usage](#usage) section for more information. + +### `addRule` + +Adds a rule to a set of rules. May be useful for conditional validations. + +```php +addRule(RuleInterface $rule): self +``` + +An example: ```php use ProgrammatorDev\YetAnotherPhpValidator\Rule; @@ -71,30 +179,29 @@ function calculateDiscount(float $price, float $discount, string $type): float } ``` -## Validation +> **Note** +> The example only shows one usage approach, but both Fluent and Dependency Injection usage approaches should work the same. +> Check the [Usage](#usage) section for more information. -### `assert` +## Exception Handling -```php -use ProgrammatorDev\YetAnotherPhpValidator\Exception\ValidationException; -use ProgrammatorDev\YetAnotherPhpValidator\Validator; +## Custom Exception Messages -// function getWeatherTemperature(float $latitude, float $longitude, string $unitSystem) +All rules have at least one error message that can be customized (some rules have more than one error message for different case scenarios). -try { - getWeatherTemperature(100, 50, 'METRIC'); -} -catch (ValidationException $exception) { - echo $exception->getMessage(); // The "Latitude" value should be between "-90" and "90", "100" given. -} -``` +Every message has a list of dynamic parameters to help create an intuitive error text (like the invalid value, constraints, names, and others). +To check what parameters and messages are available, look into the Options section in the page of a rule. +Go to [Rules](03-rules.md) to see all available rules. -### `validate` +The following example uses the [Choice](03x-rules-choice.md) rule with a custom error message: ```php use ProgrammatorDev\YetAnotherPhpValidator\Validator; -if (!Validator::range(-90, 90)->validate($latitude)) { - // do something... -} +Validator::choice( + constraints: ['red', 'green', 'blue'], + message: '"{{ value }}" is not a valid {{ name }}! You must select one of {{ constraints }}.' +)->assert('yellow', 'color'); + +// "yellow" is not a valid color! You must select one of [red, green, blue]. ``` \ No newline at end of file diff --git a/docs/03-rules-notblank.md b/docs/03-rules-notblank.md deleted file mode 100644 index cbe98cd..0000000 --- a/docs/03-rules-notblank.md +++ /dev/null @@ -1,42 +0,0 @@ -# NotBlank - -Validates that a value is not equal to a blank string, blank array, `false` or `null`. - -## Basic Usage - -```php -Validator::notBlank()->validate(''); // false -Validator::notBlank()->validate([]); // false -Validator::notBlank()->validate(false); // false -Validator::notBlank()->validate(null); // false -``` - -## Options - -```php -use ProgrammatorDev\YetAnotherPhpValidator\Rule; - -// Defaults -new Rule\NotBlank( - array $options = [ - 'normalizer' => null, - 'message' => 'The "{{ name }}" value should not be blank, "{{ value }}" given.' - ] -); -``` - -### `options` - -type: `array` - -`normalizer` - -type: `callable` default: `null` - -`message` - -type: `string` default: `The "{{ name }}" value should not be blank, "{{ value }}" given.` - - - -Normalizer \ No newline at end of file diff --git a/docs/03-rules.md b/docs/03-rules.md index 4fb9e4c..9327d44 100644 --- a/docs/03-rules.md +++ b/docs/03-rules.md @@ -1,14 +1,26 @@ # Rules -- Basic Constraints - - NotBlank -- Comparison Constraints - - LessThan - - LessThanOrEqual - - GreaterThan - - GreaterThanOrEqual - - Range -- Choice Constraints - - Choice -- Other Constraints - - All \ No newline at end of file +- [Basic Rules](#basic-rules) +- [Comparison Rules](#comparison-rules) +- [Choice Rules](#choice-rules) +- [Array Rules](#array-rules) + +## Basic Rules + +- [NotBlank](03x-rules-not-blank.md) + +## Comparison Rules + +- [GreaterThan](03x-rules-greater-than.md) +- [GreaterThanOrEqual](03x-rules-greater-than-or-equal.md) +- [LessThan](03x-rules-less-than.md) +- [LessThanOrEqual](03x-rules-less-than-or-equal.md) +- [Range](03x-rules-range.md) + +## Choice Rules + +- [Choice](03x-rules-choice.md) + +## Array Rules + +- [All](03x-rules-all.md) \ No newline at end of file diff --git a/docs/03x-rules-all.md b/docs/03x-rules-all.md new file mode 100644 index 0000000..268d287 --- /dev/null +++ b/docs/03x-rules-all.md @@ -0,0 +1,59 @@ +## All + +Validates every element of an `array` with a given set of rules. + +```php +/** + * @var RuleInterface[] $constraints + */ +All( + array $constraints, + string $message = 'At "{{ key }}": {{ message }}' +); +``` + +## Basic Usage + +```php +// One rule per array element +Validator::all([Validator::notBlank(), Validator::greaterThan(1), Validator::lessThan(10)])->validate([4, 5, 6]); // true +Validator::all([Validator::notBlank(), Validator::greaterThan(1), Validator::lessThan(10)])->validate([4, 5, 20]); // false + +// Multiple rules per array element +Validator::all([Validator::notBlank()->greaterThan(1)->lessThan(10)])->validate([4, 5, 6]); // true +``` + +> **Note** +> An `UnexpectedValueException` will be thrown if a `constraints` element does not implement a `RuleInterface`. + +> **Note** +> An `UnexpectedValueException` will be thrown when value to be validated is not an `array`. + +## Options + +### `constraints` + +type: `array` `required` + +Collection of rules, or validators, to validate each element of an `array`. +Each element must implement a `RuleInterface`, so it is possible to use a single rule or a full validator set of rules. + +### `message` + +type: `string` default: `At "{{ key }}": {{ message }}` + +Message that will be shown if at least one element of an array is invalid according to the given `constraints`. + +```php +Validator::all([Validator::notBlank()])->assert(['red', 'green', ''], 'Test'); +// Throws: At "2": The "Test" value should not be blank, "" given. +``` + +The following parameters are available: + +| Parameter | Description | +|-----------------|-----------------------------------------------| +| `{{ value }}` | The current invalid value | +| `{{ name }}` | Name of the value being validated | +| `{{ key }}` | The array key of the invalid array element | +| `{{ message }}` | The rule message of the invalid array element | \ No newline at end of file diff --git a/docs/03x-rules-choice.md b/docs/03x-rules-choice.md new file mode 100644 index 0000000..2be51f8 --- /dev/null +++ b/docs/03x-rules-choice.md @@ -0,0 +1,139 @@ +# Choice + +Validates that a value (or multiple values) exist in a given set of choices. + +```php +Choice( + array $constraints, + bool $multiple = false, + ?int $minConstraint = null, + ?int $maxConstraint = null, + string $message = 'The "{{ name }}" value is not a valid choice, "{{ value }}" given. Accepted values are: "{{ constraints }}".'; + string $multipleMessage = 'The "{{ name }}" value has one or more invalid choices, "{{ value }}" given. Accepted values are: "{{ constraints }}".'; + string $minMessage = 'The "{{ name }}" value must have at least {{ minConstraint }} choices, {{ numValues }} choices given.'; + string $maxMessage = 'The "{{ name }}" value must have at most {{ maxConstraint }} choices, {{ numValues }} choices given.'; +); +``` + +## Basic Usage + +```php +// Single choice +Validator::choice(['red', 'green', 'blue'])->validate('green'); // true +Validator::choice(['red', 'green', 'blue'])->validate('yellow'); // false + +// Multiple choices +Validator::choice(['red', 'green', 'blue'], multiple: true)->validate(['red', 'blue']); // true; +Validator::choice(['red', 'green', 'blue'], multiple: true)->validate(['red', 'yellow']); // false; + +// Multiple with minimum number of choices +Validator::choice(['red', 'green', 'blue'], multiple: true, minConstraint: 2)->validate(['red', 'blue']); // true +Validator::choice(['red', 'green', 'blue'], multiple: true, minConstraint: 2)->validate(['red']); // false + +// Multiple with maximum number of choices +Validator::choice(['red', 'green', 'blue'], multiple: true, maxConstraint: 2)->validate(['red', 'blue']); // true +Validator::choice(['red', 'green', 'blue'], multiple: true, maxConstraint: 2)->validate(['red', 'green', 'blue']); // false + +// Multiple with minimum and maximum number of choices +Validator::choice(['red', 'green', 'blue'], multiple: true, minConstraint: 2, maxConstraint: 3)->validate(['red', 'blue']); // true +Validator::choice(['red', 'green', 'blue'], multiple: true, minConstraint: 2, maxConstraint: 3)->validate(['red']); // false +``` + +> **Note** +> An `UnexpectedValueException` will be thrown when `multiple` is `true` and value to be validated is not an `array`. + +> **Note** +> An `UnexpectedValueException` will be thrown when the `minConstraint` value is greater than or equal to the `maxConstraint` value. + +## Options + +### `constraints` + +type: `array` `required` + +Collection of choices to be validated against the input value. + +### `multiple` + +type: `bool` default: `false` + +If this option is `true`, validation against an `array` of input values is enabled. +Each element of the input array must be a valid choice, otherwise it will fail. + +### `minConstraint` + +type: `?int` default: `null` + +If `multiple` is `true`, set a minimum number of input values to be required. + +For example, if `minConstraint` is 2, the input array must have at least 2 values. + +### `maxConstraint` + +type: `?int` default: `null` + +If `multiple` is `true`, set a maximum number of input values to be required. + +For example, if `maxConstraint` is 2, the input array must have at most 2 values. + +### `message` + +type `string` default: `The "{{ name }}" value is not a valid choice, "{{ value }}" given. Accepted values are: "{{ constraints }}".` + +Message that will be shown if input value is not a valid choice. + +The following parameters are available: + +| Parameter | Description | +|---------------------|-----------------------------------| +| `{{ value }}` | The current invalid value | +| `{{ name }}` | Name of the value being validated | +| `{{ constraints }}` | The array of valid choices | + +### `multipleMessage` + +type `string` default: `The "{{ name }}" value has one or more invalid choices, "{{ value }}" given. Accepted values are: "{{ constraints }}".` + +Message that will be shown when `multiple` is `true` and at least one of the input array values is not a valid choice. + +The following parameters are available: + +| Parameter | Description | +|---------------------|-----------------------------------| +| `{{ value }}` | The current invalid value | +| `{{ name }}` | Name of the value being validated | +| `{{ constraints }}` | The array of valid choices | + +### `minMessage` + +type `string` default: `The "{{ name }}" value must have at least {{ minConstraint }} choices, {{ numValues }} choices given.` + +Message that will be shown when `multiple` is `true` and input array has fewer values than the defined in `minConstraint`. + +The following parameters are available: + +| Parameter | Description | +|-----------------------|--------------------------------------| +| `{{ value }}` | The current invalid value | +| `{{ numValues }}` | The current invalid number of values | +| `{{ name }}` | Name of the value being validated | +| `{{ constraints }}` | The array of valid choices | +| `{{ minConstraint }}` | The minimum number of valid choices | +| `{{ maxConstraint }}` | The maximum number of valid choices | + +### `maxMessage` + +type `string` default: `The "{{ name }}" value must have at most {{ maxConstraint }} choices, {{ numValues }} choices given.` + +Message that will be shown when `multiple` is `true` and input array has more values than the defined in `maxConstraint`. + +The following parameters are available: + +| Parameter | Description | +|-----------------------|--------------------------------------| +| `{{ value }}` | The current invalid value | +| `{{ numValues }}` | The current invalid number of values | +| `{{ name }}` | Name of the value being validated | +| `{{ constraints }}` | The array of valid choices | +| `{{ minConstraint }}` | The minimum number of valid choices | +| `{{ maxConstraint }}` | The maximum number of valid choices | \ No newline at end of file diff --git a/docs/03x-rules-greater-than-or-equal.md b/docs/03x-rules-greater-than-or-equal.md new file mode 100644 index 0000000..a8cb9d7 --- /dev/null +++ b/docs/03x-rules-greater-than-or-equal.md @@ -0,0 +1,57 @@ +# GreaterThanOrEqual + +Validates that a value is greater than or equal to another value. +Can compare between strings, numbers and dates. + +```php +GreaterThanOrEqual( + mixed $constraint, + string $message = 'The "{{ name }}" value should be greater than or equal to "{{ constraint }}", "{{ value }}" given.' +); +``` + +## Basic Usage + +```php +Validator::greaterThanOrEqual(10)->validate(20); // true +Validator::greaterThanOrEqual(10)->validate(10); // true + +Validator::greaterThanOrEqual(1.5)->validate(2.5); // true +Validator::greaterThanOrEqual(1.5)->validate(1.5); // true + +Validator::greaterThanOrEqual('alpha')->validate('beta'); // true +Validator::greaterThanOrEqual('alpha')->validate('alpha'); // true + +Validator::greaterThanOrEqual(new DateTime('today'))->validate(new DateTime('tomorrow')); // true +Validator::greaterThanOrEqual(new DateTime('today'))->validate(new DateTime('today')); // true +``` + +> **Note** +> String comparison is case-sensitive, meaning that comparing `'hello'` with `'Hello'` is different. +> Check [`strcmp`](https://www.php.net/manual/en/function.strcmp.php) for more information. + +> **Note** +> An `UnexpectedValueException` will be thrown when trying to compare incomparable values, like a `string` with an `int`. + +## Options + +### `constraint` + +type: `mixed` `required` + +It defines the comparison/minimum value. +Can be a `string`, `int`, `float` or `DateTimeInterface` object. + +### `message` + +type: `string` default: `The "{{ name }}" value should be greater than or equal to "{{ constraint }}", "{{ value }}" given.` + +Message that will be shown if the value is not greater than or equal to the constraint value. + +The following parameters are available: + +| Parameter | Description | +|--------------------|-----------------------------------| +| `{{ value }}` | The current invalid value | +| `{{ name }}` | Name of the value being validated | +| `{{ constraint }}` | The comparison value | \ No newline at end of file diff --git a/docs/03x-rules-greater-than.md b/docs/03x-rules-greater-than.md new file mode 100644 index 0000000..2f4f019 --- /dev/null +++ b/docs/03x-rules-greater-than.md @@ -0,0 +1,57 @@ +# GreaterThan + +Validates that a value is greater than another value. +Can compare between strings, numbers and dates. + +```php +GreaterThan( + mixed $constraint, + string $message = 'The "{{ name }}" value should be greater than "{{ constraint }}", "{{ value }}" given.' +); +``` + +## Basic Usage + +```php +Validator::greaterThan(10)->validate(20); // true +Validator::greaterThan(10)->validate(10); // false + +Validator::greaterThan(1.5)->validate(2.5); // true +Validator::greaterThan(1.5)->validate(1.5); // false + +Validator::greaterThan('alpha')->validate('beta'); // true +Validator::greaterThan('alpha')->validate('alpha'); // false + +Validator::greaterThan(new DateTime('today'))->validate(new DateTime('tomorrow')); // true +Validator::greaterThan(new DateTime('today'))->validate(new DateTime('today')); // false +``` + +> **Note** +> String comparison is case-sensitive, meaning that comparing `'hello'` with `'Hello'` is different. +> Check [`strcmp`](https://www.php.net/manual/en/function.strcmp.php) for more information. + +> **Note** +> An `UnexpectedValueException` will be thrown when trying to compare incomparable values, like a `string` with an `int`. + +## Options + +### `constraint` + +type: `mixed` `required` + +It defines the comparison/minimum value. +Can be a `string`, `int`, `float` or `DateTimeInterface` object. + +### `message` + +type: `string` default: `The "{{ name }}" value should be greater than "{{ constraint }}", "{{ value }}" given.` + +Message that will be shown if the value is not greater than the constraint value. + +The following parameters are available: + +| Parameter | Description | +|--------------------|-----------------------------------| +| `{{ value }}` | The current invalid value | +| `{{ name }}` | Name of the value being validated | +| `{{ constraint }}` | The comparison value | \ No newline at end of file diff --git a/docs/03x-rules-less-than-or-equal.md b/docs/03x-rules-less-than-or-equal.md new file mode 100644 index 0000000..34a3e6c --- /dev/null +++ b/docs/03x-rules-less-than-or-equal.md @@ -0,0 +1,57 @@ +# LessThanOrEqual + +Validates that a value is less than or equal to another value. +Can compare between strings, numbers and dates. + +```php +LessThanOrEqual( + mixed $constraint, + string $message = 'The "{{ name }}" value should be less than or equal to "{{ constraint }}", "{{ value }}" given.' +); +``` + +## Basic Usage + +```php +Validator::lessThanOrEqual(20)->validate(10); // true +Validator::lessThanOrEqual(10)->validate(10); // true + +Validator::lessThanOrEqual(2.5)->validate(1.5); // true +Validator::lessThanOrEqual(1.5)->validate(1.5); // true + +Validator::lessThanOrEqual('beta')->validate('alpha'); // true +Validator::lessThanOrEqual('alpha')->validate('alpha'); // true + +Validator::lessThanOrEqual(new DateTime('today'))->validate(new DateTime('yesterday')); // true +Validator::lessThanOrEqual(new DateTime('today'))->validate(new DateTime('today')); // true +``` + +> **Note** +> String comparison is case-sensitive, meaning that comparing `'hello'` with `'Hello'` is different. +> Check [`strcmp`](https://www.php.net/manual/en/function.strcmp.php) for more information. + +> **Note** +> An `UnexpectedValueException` will be thrown when trying to compare incomparable values, like a `string` with an `int`. + +## Options + +### `constraint` + +type: `mixed` `required` + +It defines the comparison/maximum value. +Can be a `string`, `int`, `float` or `DateTimeInterface` object. + +### `message` + +type: `string` default: `The "{{ name }}" value should be less than or equal to "{{ constraint }}", "{{ value }}" given.` + +Message that will be shown if the value is not less than or equal to the constraint value. + +The following parameters are available: + +| Parameter | Description | +|--------------------|-----------------------------------| +| `{{ value }}` | The current invalid value | +| `{{ name }}` | Name of the value being validated | +| `{{ constraint }}` | The comparison value | \ No newline at end of file diff --git a/docs/03x-rules-less-than.md b/docs/03x-rules-less-than.md new file mode 100644 index 0000000..a01b52f --- /dev/null +++ b/docs/03x-rules-less-than.md @@ -0,0 +1,57 @@ +# LessThan + +Validates that a value is less than another value. +Can compare between strings, numbers and dates. + +```php +LessThan( + mixed $constraint, + string $message = 'The "{{ name }}" value should be less than "{{ constraint }}", "{{ value }}" given.' +); +``` + +## Basic Usage + +```php +Validator::lessThan(20)->validate(10); // true +Validator::lessThan(20)->validate(20); // false + +Validator::lessThan(2.5)->validate(1.5); // true +Validator::lessThan(2.5)->validate(2.5); // false + +Validator::lessThan('beta')->validate('alpha'); // true +Validator::lessThan('beta')->validate('beta'); // false + +Validator::lessThan(new DateTime('today'))->validate(new DateTime('yesterday')); // true +Validator::lessThan(new DateTime('today'))->validate(new DateTime('today')); // false +``` + +> **Note** +> String comparison is case-sensitive, meaning that comparing `'hello'` with `'Hello'` is different. +> Check [`strcmp`](https://www.php.net/manual/en/function.strcmp.php) for more information. + +> **Note** +> An `UnexpectedValueException` will be thrown when trying to compare incomparable values, like a `string` with an `int`. + +## Options + +### `constraint` + +type: `mixed` `required` + +It defines the comparison/maximum value. +Can be a `string`, `int`, `float` or `DateTimeInterface` object. + +### `message` + +type: `string` default: `The "{{ name }}" value should be less than "{{ constraint }}", "{{ value }}" given.` + +Message that will be shown if the value is not less than the constraint value. + +The following parameters are available: + +| Parameter | Description | +|--------------------|-----------------------------------| +| `{{ value }}` | The current invalid value | +| `{{ name }}` | Name of the value being validated | +| `{{ constraint }}` | The comparison value | \ No newline at end of file diff --git a/docs/03x-rules-not-blank.md b/docs/03x-rules-not-blank.md new file mode 100644 index 0000000..c77f476 --- /dev/null +++ b/docs/03x-rules-not-blank.md @@ -0,0 +1,53 @@ +# NotBlank + +Validates that a value is not equal to a blank string, blank array, `false` or `null`. + +```php +NotBlank( + ?callable $normalizer = null, + string $message = 'The "{{ name }}" value should not be blank, "{{ value }}" given.' +); +``` + +## Basic Usage + +Bellow are the only cases where the rule will fail, everything else is considered valid +(you may want to check the [`normalizer`](#normalizer) option for a different behaviour): + +```php +Validator::notBlank()->validate(''); // false +Validator::notBlank()->validate([]); // false +Validator::notBlank()->validate(false); // false +Validator::notBlank()->validate(null); // false +``` + +## Options + +### `normalizer` + +type: `callable` default: `null` + +Allows to define a `callable` that will be applied to the value before checking if it is valid. + +For example, use `trim`, or pass your own function, to now allow a string with whitespaces only: + +```php +// Existing PHP callables +Validator::notBlank(normalizer: 'trim')->validate(' '); // false + +// Function +Validator::notBlank(normalizer: fn($value) => trim($value))->validate(' '); // false +``` + +### `message` + +type: `string` default: `The "{{ name }}" value should not be blank, "{{ value }}" given.` + +Message that will be shown if the value is blank. + +The following parameters are available: + +| Parameter | Description | +|---------------|-----------------------------------| +| `{{ value }}` | The current invalid value | +| `{{ name }}` | Name of the value being validated | \ No newline at end of file diff --git a/docs/03x-rules-range.md b/docs/03x-rules-range.md new file mode 100644 index 0000000..dccc32d --- /dev/null +++ b/docs/03x-rules-range.md @@ -0,0 +1,72 @@ +# Range + +Validates that a value is between a minimum and maximum value. +Can compare between strings, numbers and dates. + +```php +Range( + mixed $minConstraint, + mixed $maxConstraint, + string $message = 'The "{{ name }}" value should be between "{{ minConstraint }}" and "{{ maxConstraint }}", "{{ value }}" given.' +); +``` + +## Basic Usage + +Values equal to the defined minimum and maximum constraints are considered valid. + +```php +Validator::range(1, 20)->validate(10); // true +Validator::range(1, 20)->validate(1); // true + +Validator::range(1.5, 3.5)->validate(2.5); // true +Validator::range(1.5, 3.5)->validate(3.5); // true + +Validator::range('alpha', 'gamma')->validate('beta'); // true +Validator::range('alpha', 'gamma')->validate('alpha'); // true + +Validator::range(new DateTime('yesterday'), new DateTime('tomorrow'))->validate(new DateTime('today')); // true +Validator::range(new DateTime('yesterday'), new DateTime('tomorrow'))->validate(new DateTime('tomorrow')); // true +``` + +> **Note** +> String comparison is case-sensitive, meaning that comparing `'hello'` with `'Hello'` is different. +> Check [`strcmp`](https://www.php.net/manual/en/function.strcmp.php) for more information. + +> **Note** +> An `UnexpectedValueException` will be thrown when trying to compare incomparable values, like a `string` with an `int`. + +> **Note** +> An `UnexpectedValueException` will be thrown when the `minConstraint` value is greater than or equal to the `maxConstraint` value. + +## Options + +### `minConstraint` + +type: `mixed` `required` + +It defines the minimum range value. +Can be a `string`, `int`, `float` or `DateTimeInterface` object. + +### `maxConstraint` + +type: `mixed` `required` + +It defines the maximum range value. +Can be a `string`, `int`, `float` or `DateTimeInterface` object. + +### `message` + +type: `string` default: `The "{{ name }}" value should be between "{{ minConstraint }}" and "{{ maxConstraint }}", "{{ value }}" given.` + +Message that will be shown if the value is not between the minimum and maximum constraint values. +Check the [Custom Messages]() section for more information. + +The following parameters are available: + +| Parameter | Description | +|-----------------------|-----------------------------------| +| `{{ value }}` | The current invalid value | +| `{{ name }}` | Name of the value being validated | +| `{{ minConstraint }}` | The minimum range value | +| `{{ maxConstraint }}` | The maximum range value | \ No newline at end of file diff --git a/src/Rule/Range.php b/src/Rule/Range.php index 12302ef..25497bf 100644 --- a/src/Rule/Range.php +++ b/src/Rule/Range.php @@ -32,20 +32,13 @@ public function assert(mixed $value, string $name): void ); } - if ( - !Validator::greaterThan($this->minConstraint) - ->validate($this->maxConstraint) - ) { + if (!Validator::greaterThan($this->minConstraint)->validate($this->maxConstraint)) { throw new UnexpectedValueException( 'Max constraint value must be greater than min constraint value.' ); } - if ( - !Validator::greaterThanOrEqual($this->minConstraint) - ->lessThanOrEqual($this->maxConstraint) - ->validate($value) - ) { + if (!Validator::greaterThanOrEqual($this->minConstraint)->lessThanOrEqual($this->maxConstraint)->validate($value)) { throw new RangeException( message: $this->message, parameters: [