Validation ¶
Validation is a very common task in web applications. Data entered in forms needs to be validated. Data also needs to be validated before it is written into a database or passed to a web service.
Symfony provides a Validator component to handle this for you. This component is based on the JSR303 Bean Validation specification.
Installation ¶
In applications using Symfony Flex, run this command to install the validator before using it:
1 |
$ composer require symfony/validator
|
Note
If your application doesn't use Symfony Flex, you might need to do some manual configuration to enable validation. Check out the Validation configuration reference.
The Basics of Validation ¶
The best way to understand validation is to see it in action. To start, suppose you've created a plain-old-PHP object that you need to use somewhere in your application:
1 2 3 4 5 6 7 |
// src/Entity/Author.php
namespace App\Entity;
class Author
{
private $name;
}
|
So far, this is an ordinary class that serves some purpose inside your
application. The goal of validation is to tell you if the data of an object is
valid. For this to work, you'll configure a list of rules (called
constraints) that the object must follow in
order to be valid. These rules are usually defined using PHP code or
attributes but they can also be defined as .yaml
or .xml
files inside
the config/validator/
directory:
For example, to indicate that the $name
property must not be empty, add the
following:
-
Attributes
属性
-
YAML
YAML
-
XML
XML
-
PHP
PHP
1 2 3 4 5 6 7 8 9 10 11 |
// src/Entity/Author.php
namespace App\Entity;
// ...
use Symfony\Component\Validator\Constraints as Assert;
class Author
{
#[Assert\NotBlank]
private $name;
}
|
Adding this configuration by itself does not yet guarantee that the value will not be blank; you can still set it to a blank value if you want. To actually guarantee that the value adheres to the constraint, the object must be passed to the validator service to be checked.
Tip
Symfony's validator uses PHP reflection, as well as "getter" methods, to get the value of any property, so they can be public, private or protected (see Validation).
Using the Validator Service ¶
Next, to actually validate an Author
object, use the validate()
method
on the validator
service (which implements ValidatorInterface).
The job of the validator
is to read the constraints (i.e. rules)
of a class and verify if the data on the object satisfies those
constraints. If validation fails, a non-empty list of errors
(ConstraintViolationList class) is
returned. Take this simple example from inside a controller:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
// ...
use App\Entity\Author;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Validator\Validator\ValidatorInterface;
// ...
public function author(ValidatorInterface $validator)
{
$author = new Author();
// ... do something to the $author object
$errors = $validator->validate($author);
if (count($errors) > 0) {
/*
* Uses a __toString method on the $errors variable which is a
* ConstraintViolationList object. This gives us a nice string
* for debugging.
*/
$errorsString = (string) $errors;
return new Response($errorsString);
}
return new Response('The author is valid! Yes!');
}
|
If the $name
property is empty, you will see the following error
message:
1 2 |
Object(App\Entity\Author).name:
This value should not be blank.
|
If you insert a value into the name
property, the happy success message
will appear.
Tip
Most of the time, you won't interact directly with the validator
service or need to worry about printing out the errors. Most of the time,
you'll use validation indirectly when handling submitted form data. For
more information, see how to validate Symfony forms.
You could also pass the collection of errors into a template:
1 2 3 4 5 |
if (count($errors) > 0) {
return $this->render('author/validation.html.twig', [
'errors' => $errors,
]);
}
|
Inside the template, you can output the list of errors exactly as needed:
1 2 3 4 5 6 7 |
{# templates/author/validation.html.twig #}
<h3>The author has the following errors</h3>
<ul>
{% for error in errors %}
<li>{{ error.message }}</li>
{% endfor %}
</ul>
|
Note
Each validation error (called a "constraint violation"), is represented by a ConstraintViolation object.
Validation Callables ¶
The Validation
also allows you to create a closure to validate values
against a set of constraints (useful for example when
validating Console command answers or
when validating OptionsResolver values):
- createCallable()
-
This returns a closure that throws
ValidationFailedException
when the constraints aren't matched.これは、制約が一致しない場合に ValidationFailedException をスローするクロージャーを返します。 - createIsValidCallable()
-
This returns a closure that returns
false
when the constraints aren't matched.これは、制約が一致しない場合に false を返すクロージャーを返します。 - .. index::
-
single: Validation; Constraints
シングル: 検証;制約
Constraints ¶
The validator
is designed to validate objects against constraints (i.e.
rules). In order to validate an object, simply map one or more constraints
to its class and then pass it to the validator
service.
Behind the scenes, a constraint is simply a PHP object that makes an assertive
statement. In real life, a constraint could be: 'The cake must not be burned'
.
In Symfony, constraints are similar: they are assertions that a condition
is true. Given a value, a constraint will tell you if that value
adheres to the rules of the constraint.
Supported Constraints ¶
Symfony packages many of the most commonly-needed constraints:
Basic Constraints ¶
These are the basic constraints: use them to assert very basic things about the value of properties or the return value of methods on your object.
String Constraints ¶
- EmailEメール
- ExpressionSyntax式構文
- Length長さ
- UrlURL
- Regex正規表現
- Hostnameホスト名
- Ipイップ
- Cidrシドル
- Jsonジェイソン
- Uuidウイド
- Ulidウリド
- UserPassword利用者パスワード
- NotCompromisedPassword侵害されていないパスワード
- CssColorCssColor
Comparison Constraints ¶
- EqualToに等しい
- NotEqualTo等しくない
- IdenticalToと同じ
- NotIdenticalToNotIdenticalTo
- LessThan未満
- LessThanOrEqualLessThanOrEqual
- GreaterThanより大きい
- GreaterThanOrEqualGreaterThanOrEqual
- Range範囲
- DivisibleBy割り切れる
- Unique個性的
Number Constraints ¶
- Positiveポジティブ
- PositiveOrZeroポジティブまたはゼロ
- Negativeネガティブ
- NegativeOrZeroNegativeOrZero
Financial and other Number Constraints ¶
Other Constraints ¶
- AtLeastOneOfAtLeastOneOf
- Sequentially順次
- Compoundコンパウンド
- Callback折り返し電話
- Expression表現
- Whenいつ
- All全て
- Valid有効
- Traverseトラバース
- Collectionコレクション
- Countカウント
- UniqueEntityUniqueEntity
You can also create your own custom constraints. This topic is covered in the How to Create a Custom Validation Constraint article.
Constraint Configuration ¶
Some constraints, like NotBlank,
are simple whereas others, like the Choice
constraint, have several configuration options available. Suppose that the
Author
class has another property called genre
that defines the
literature genre mostly associated with the author, which can be set to either
"fiction" or "non-fiction":
-
Attributes
属性
-
YAML
YAML
-
XML
XML
-
PHP
PHP
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
// src/Entity/Author.php
namespace App\Entity;
// ...
use Symfony\Component\Validator\Constraints as Assert;
class Author
{
#[Assert\Choice(
choices: ['fiction', 'non-fiction'],
message: 'Choose a valid genre.',
)]
private $genre;
// ...
}
|
The options of a constraint can always be passed in as an array. Some constraints,
however, also allow you to pass the value of one, "default", option in place
of the array. In the case of the Choice
constraint, the choices
options can be specified in this way.
-
Attributes
属性
-
YAML
YAML
-
XML
XML
-
PHP
PHP
1 2 3 4 5 6 7 8 9 10 11 12 13 |
// src/Entity/Author.php
namespace App\Entity;
// ...
use Symfony\Component\Validator\Constraints as Assert;
class Author
{
#[Assert\Choice(['fiction', 'non-fiction'])]
private $genre;
// ...
}
|
This is purely meant to make the configuration of the most common option of a constraint shorter and quicker.
If you're ever unsure of how to specify an option, either check the namespace
Symfony\Component\Validator\Constraints
for the constraint or play it safe
by always passing in an array of options (the first method shown above).
Constraints in Form Classes ¶
Constraints can be defined while building the form via the constraints
option
of the form fields:
1 2 3 4 5 6 7 8 9 |
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('myField', TextType::class, [
'required' => true,
'constraints' => [new Length(['min' => 3])],
])
;
}
|
Constraint Targets ¶
Constraints can be applied to a class property (e.g. name
),
a getter method (e.g. getFullName()
) or an entire class. Property constraints
are the most common and easy to use. Getter constraints allow you to specify
more complex validation rules. Finally, class constraints are intended
for scenarios where you want to validate a class as a whole.
Properties ¶
Validating class properties is the most basic validation technique. Symfony
allows you to validate private, protected or public properties. The next
listing shows you how to configure the $firstName
property of an Author
class to have at least 3 characters.
-
Attributes
属性
-
YAML
YAML
-
XML
XML
-
PHP
PHP
1 2 3 4 5 6 7 8 9 10 11 |
// src/Entity/Author.php
// ...
use Symfony\Component\Validator\Constraints as Assert;
class Author
{
#[Assert\NotBlank]
#[Assert\Length(min: 3)]
private $firstName;
}
|
Caution
The validator will use a value null
if a typed property is uninitialized.
This can cause unexpected behavior if the property holds a value when initialized.
In order to avoid this, make sure all properties are initialized before validating them.
Getters ¶
Constraints can also be applied to the return value of a method. Symfony allows you to add a constraint to any private, protected or public method whose name starts with "get", "is" or "has". In this guide, these types of methods are referred to as "getters".
The benefit of this technique is that it allows you to validate your object
dynamically. For example, suppose you want to make sure that a password field
doesn't match the first name of the user (for security reasons). You can
do this by creating an isPasswordSafe()
method, and then asserting that
this method must return true
:
-
Attributes
属性
-
YAML
YAML
-
XML
XML
-
PHP
PHP
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
// src/Entity/Author.php
namespace App\Entity;
// ...
use Symfony\Component\Validator\Constraints as Assert;
class Author
{
#[Assert\IsTrue(message: 'The password cannot match your first name')]
public function isPasswordSafe()
{
// ... return true or false
}
}
|
Now, create the isPasswordSafe()
method and include the logic you need:
1 2 3 4 |
public function isPasswordSafe()
{
return $this->firstName !== $this->password;
}
|
Note
The keen-eyed among you will have noticed that the prefix of the getter ("get", "is" or "has") is omitted in the mappings for the YAML, XML and PHP formats. This allows you to move the constraint to a property with the same name later (or vice versa) without changing your validation logic.
Classes ¶
Some constraints apply to the entire class being validated. For example, the Callback constraint is a generic constraint that's applied to the class itself. When that class is validated, methods specified by that constraint are simply executed so that each can provide more custom validation.
Debugging the Constraints ¶
Use the debug:validator
command to list the validation constraints of a
given class:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
$ php bin/console debug:validator 'App\Entity\SomeClass'
App\Entity\SomeClass
-----------------------------------------------------
+---------------+--------------------------------------------------+---------+------------------------------------------------------------+
| Property | Name | Groups | Options |
+---------------+--------------------------------------------------+---------+------------------------------------------------------------+
| firstArgument | Symfony\Component\Validator\Constraints\NotBlank | Default | [ |
| | | | "message" => "This value should not be blank.", |
| | | | "allowNull" => false, |
| | | | "normalizer" => null, |
| | | | "payload" => null |
| | | | ] |
| firstArgument | Symfony\Component\Validator\Constraints\Email | Default | [ |
| | | | "message" => "This value is not a valid email address.", |
| | | | "mode" => null, |
| | | | "normalizer" => null, |
| | | | "payload" => null |
| | | | ] |
+---------------+--------------------------------------------------+---------+------------------------------------------------------------+
|
You can also validate all the classes stored in a given directory:
1 |
$ php bin/console debug:validator src/Entity
|
Final Thoughts ¶
The Symfony validator
is a powerful tool that can be leveraged to
guarantee that the data of any object is "valid". The power behind validation
lies in "constraints", which are rules that you can apply to properties or
getter methods of your object. And while you'll most commonly use the validation
framework indirectly when using forms, remember that it can be used anywhere
to validate any object.
Learn more ¶
- How to Create a Custom Validation Constraintカスタム検証制約を作成する方法
- How to Apply only a Subset of all Your Validation Constraints (Validation Groups)すべての検証制約 (検証グループ) のサブセットのみを適用する方法
- How to Validate Raw Values (Scalar Values and Arrays)生の値 (スカラー値と配列) を検証する方法
- How to Sequentially Apply Validation Groups検証グループを順次適用する方法
- How to Handle Different Error Levelsさまざまなエラー レベルの処理方法
- How to Translate Validation Constraint Messages検証制約メッセージを翻訳する方法