mirror of
https://github.com/Respect/Validation.git
synced 2024-06-17 04:55:05 +02:00
The documentation about custom rules does not specify that creating an exception for the rule is necessary. This commit will add that to the documentation with an example to make it explicit. Co-authored-by: Henrique Moody <henriquemoody@gmail.com>
326 lines
9 KiB
Markdown
326 lines
9 KiB
Markdown
# Feature Guide
|
|
|
|
## Namespace import
|
|
|
|
Respect\Validation is namespaced, but you can make your life easier by importing
|
|
a single class into your context:
|
|
|
|
```php
|
|
use Respect\Validation\Validator as v;
|
|
```
|
|
|
|
## Simple validation
|
|
|
|
The Hello World validator is something like this:
|
|
|
|
```php
|
|
$number = 123;
|
|
v::numeric()->validate($number); // true
|
|
```
|
|
|
|
## Chained validation
|
|
|
|
It is possible to use validators in a chain. Sample below validates a string
|
|
containing numbers and letters, no whitespace and length between 1 and 15.
|
|
|
|
```php
|
|
$usernameValidator = v::alnum()->noWhitespace()->length(1, 15);
|
|
$usernameValidator->validate('alganet'); // true
|
|
```
|
|
|
|
## Validating object attributes
|
|
|
|
Given this simple object:
|
|
|
|
```php
|
|
$user = new stdClass;
|
|
$user->name = 'Alexandre';
|
|
$user->birthdate = '1987-07-01';
|
|
```
|
|
|
|
Is possible to validate its attributes in a single chain:
|
|
|
|
```php
|
|
$userValidator = v::attribute('name', v::stringType()->length(1,32))
|
|
->attribute('birthdate', v::date()->age(18));
|
|
|
|
$userValidator->validate($user); // true
|
|
```
|
|
|
|
Validating array keys is also possible using `v::key()`
|
|
|
|
Note that we used `v::stringType()` and `v::date()` in the beginning of the validator.
|
|
Although is not mandatory, it is a good practice to use the type of the
|
|
validated object as the first node in the chain.
|
|
|
|
## Input optional
|
|
|
|
On oldest versions of Respect\Validation all validators treat input as optional
|
|
and accept an empty string input as valid. Even though a useful feature that
|
|
caused a lot of troubles for our team and neither was an obvious behavior. Also
|
|
there was some people who likes to accept `null` as optional value, not only an
|
|
empty string.
|
|
|
|
For that reason all rules are mandatory now but if you want to treat a value as
|
|
optional you can use `v::optional()` rule:
|
|
|
|
```php
|
|
v::alpha()->validate(''); // false input required
|
|
v::alpha()->validate(null); // false input required
|
|
|
|
v::optional(v::alpha())->validate(''); // true
|
|
v::optional(v::alpha())->validate(null); // true
|
|
```
|
|
|
|
By _optional_ we consider `null` or an empty string (`''`).
|
|
|
|
See more on [Optional](rules/Optional.md).
|
|
|
|
## Negating rules
|
|
|
|
You can use the `v::not()` to negate any rule:
|
|
|
|
```php
|
|
v::not(v::intVal())->validate(10); // false, input must not be integer
|
|
```
|
|
|
|
## Validator reuse
|
|
|
|
Once created, you can reuse your validator anywhere. Remember `$usernameValidator`?
|
|
|
|
```php
|
|
$usernameValidator->validate('respect'); //true
|
|
$usernameValidator->validate('alexandre gaigalas'); // false
|
|
$usernameValidator->validate('#$%'); //false
|
|
```
|
|
|
|
## Exception types
|
|
|
|
* `Respect\Validation\Exceptions\ExceptionInterface`:
|
|
* All exceptions implement this interface;
|
|
* `Respect\Validation\Exceptions\ValidationException`:
|
|
* Implements the `Respect\Validation\Exceptions\ExceptionInterface` interface
|
|
* Thrown when the `check()` fails
|
|
* All validation exceptions extend this class
|
|
* Available methods:
|
|
* `getMainMessage()`;
|
|
* `setMode($mode)`;
|
|
* `setName($name)`;
|
|
* `setParam($name, $value)`;
|
|
* `setTemplate($template)`;
|
|
* more...
|
|
* `Respect\Validation\Exceptions\NestedValidationException`:
|
|
* Extends the `Respect\Validation\Exceptions\ValidationException` class
|
|
* Usually thrown when the `assert()` fails
|
|
* Available methods:
|
|
* `findMessages()`;
|
|
* `getFullMessage()`;
|
|
* `getMessages()`;
|
|
* more...
|
|
|
|
## Informative exceptions
|
|
|
|
When something goes wrong, Validation can tell you exactly what's going on. For this,
|
|
we use the `assert()` method instead of `validate()`:
|
|
|
|
```php
|
|
use Respect\Validation\Exceptions\NestedValidationException;
|
|
|
|
try {
|
|
$usernameValidator->assert('really messed up screen#name');
|
|
} catch(NestedValidationException $exception) {
|
|
echo $exception->getFullMessage();
|
|
}
|
|
```
|
|
|
|
The printed message is exactly this, as a nested Markdown list:
|
|
|
|
```no-highlight
|
|
- All of the required rules must pass for "really messed up screen#name"
|
|
- "really messed up screen#name" must contain only letters (a-z) and digits (0-9)
|
|
- "really messed up screen#name" must not contain whitespace
|
|
- "really messed up screen#name" must have a length between 1 and 15
|
|
```
|
|
|
|
## Getting all messages as an array
|
|
|
|
The Markdown list is fine, but unusable on a HTML form or something more custom.
|
|
For that you can use `getMessages()`.
|
|
|
|
It will return all messages from the rules that did not pass the validation.
|
|
|
|
```php
|
|
try {
|
|
$usernameValidator->assert('really messed up screen#name');
|
|
} catch(NestedValidationException $exception) {
|
|
print_r($exception->getMessages());
|
|
}
|
|
```
|
|
|
|
The code above may display something like:
|
|
|
|
```no-highlight
|
|
Array
|
|
(
|
|
[0] => "really messed up screen#name" must contain only letters (a-z) and digits (0-9)
|
|
[1] => "really messed up screen#name" must not contain whitespace
|
|
[2] => "really messed up screen#name" must have a length between 1 and 15
|
|
)
|
|
```
|
|
|
|
## Getting messages as an array by name
|
|
|
|
If you want to get specific message by name you can use `findMessages()` passing
|
|
the names of the rules you want:
|
|
|
|
```php
|
|
try {
|
|
$usernameValidator->assert('really messed up screen#name');
|
|
} catch(NestedValidationException $exception) {
|
|
print_r($exception->findMessages(['alnum', 'noWhitespace']));
|
|
}
|
|
```
|
|
|
|
The `findMessages()` returns an array with messages from the requested validators,
|
|
like this:
|
|
|
|
```no-highlight
|
|
Array
|
|
(
|
|
[alnum] => "really messed up screen#name" must contain only letters (a-z) and digits (0-9)
|
|
[noWhitespace] => "really messed up screen#name" must not contain whitespace
|
|
)
|
|
```
|
|
|
|
## Custom messages
|
|
|
|
Getting messages as an array is fine, but sometimes you need to customize them in order
|
|
to present them to the user. This is possible using the `findMessages()` method as well:
|
|
|
|
```php
|
|
$errors = $exception->findMessages([
|
|
'alnum' => '{{name}} must contain only letters and digits',
|
|
'length' => '{{name}} must not have more than 15 chars',
|
|
'noWhitespace' => '{{name}} cannot contain spaces'
|
|
]);
|
|
```
|
|
|
|
For all messages, the `{{name}}` variable is available for templates. If you
|
|
do not define a name it uses the input to replace this placeholder.
|
|
|
|
## Message localization
|
|
|
|
You're also able to translate your message to another language with Validation.
|
|
The only thing one must do is to define the param `translator` as a callable that
|
|
will handle the translation:
|
|
|
|
```php
|
|
$exception->setParam('translator', 'gettext');
|
|
```
|
|
|
|
The example above uses `gettext()` but you can use any other callable value, like
|
|
`[$translator, 'trans']` or `you_custom_function()`.
|
|
|
|
After that, if you call `getMainMessage()` or `getFullMessage()` (for nested),
|
|
the message will be translated.
|
|
|
|
Note that `getMessage()` will keep the original message.
|
|
|
|
## Custom rules
|
|
|
|
You also can use your own rules:
|
|
|
|
```php
|
|
namespace My\Validation\Rules;
|
|
|
|
use Respect\Validation\Rules\AbstractRule;
|
|
|
|
class MyRule extends AbstractRule
|
|
{
|
|
public function validate($input)
|
|
{
|
|
// Do something here with the $input and return a boolean value
|
|
}
|
|
}
|
|
```
|
|
|
|
If you do want Validation to execute you rule (or rules) in the chain, you must
|
|
use `v::with()` passing your rule's namespace as an argument:
|
|
|
|
```php
|
|
v::with('My\\Validation\\Rules\\');
|
|
v::myRule(); // Try to load "My\Validation\Rules\MyRule" if any
|
|
```
|
|
|
|
By default `with()` appends the given prefix, but you can change this behavior
|
|
in order to overwrite default rules:
|
|
|
|
```php
|
|
v::with('My\\Validation\\Rules', true);
|
|
v::alnum(); // Try to use "My\Validation\Rules\Alnum" if any
|
|
```
|
|
|
|
If you're using the `assert()` or `check()` methods you also need to create an
|
|
Exception to declare the messages returned:
|
|
|
|
```php
|
|
namespace My\Validation\Exceptions;
|
|
|
|
use Respect\Validation\Exceptions\ValidationException;
|
|
|
|
class MyRuleException extends ValidationException
|
|
{
|
|
public static $defaultTemplates = [
|
|
self::MODE_DEFAULT => [
|
|
self::STANDARD => '{{name}} must pass my rules',
|
|
],
|
|
self::MODE_NEGATIVE => [
|
|
self::STANDARD => '{{name}} must not pass my rules',
|
|
]
|
|
];
|
|
}
|
|
```
|
|
|
|
Notice that while the namespace of the rule is `My\Validation\Rules` the
|
|
namespace of the exception is `My\Validation\Exceptions`.
|
|
|
|
## Validator name
|
|
|
|
On `v::attribute()` and `v::key()`, `{{name}}` is the attribute/key name. For others,
|
|
is the same as the input. You can customize a validator name using:
|
|
|
|
```php
|
|
v::date('Y-m-d')->between('1980-02-02', 'now')->setName('Member Since');
|
|
```
|
|
|
|
## Zend/Symfony validators
|
|
|
|
It is also possible to reuse validators from other frameworks if they are installed:
|
|
|
|
```php
|
|
$hostnameValidator = v::zend('Hostname')->assert('google.com');
|
|
$timeValidator = v::sf('Time')->assert('22:00:01');
|
|
```
|
|
|
|
## Validation methods
|
|
|
|
We've seen `validate()` that returns true or false and `assert()` that throws a complete
|
|
validation report. There is also a `check()` method that returns an Exception
|
|
only with the first error found:
|
|
|
|
```php
|
|
use Respect\Validation\Exceptions\ValidationException;
|
|
|
|
try {
|
|
$usernameValidator->check('really messed up screen#name');
|
|
} catch(ValidationException $exception) {
|
|
echo $exception->getMainMessage();
|
|
}
|
|
```
|
|
|
|
Message:
|
|
|
|
```no-highlight
|
|
"really messed up screen#name" must contain only letters (a-z) and digits (0-9)
|
|
```
|