Валідація
Дата оновлення перекладу 2024-06-10
Валідація
Валідація - це дуже розповсюджена задача для веб-додатку. Дані, які вводяться у форми, мають бути валідовані (перевірені). У той же час, дані мають бути валідовані до того, як вони будуть записані в базу даних або ж передані веб-сервісу.
Symfony містить компонент Validator, який спрощує цю задачу. Цей компонент заснований на документі специфікація валідації JSR303 Bean.
Установка
В додатках, які використовують Symfony Flex , виконайте цю команду, щоб встановити валідатор перед його використанням:
1
$ composer require symfony/validator doctrine/annotations
Note
Якщо ваш застосунок не використовує Symfony Flex, вам може знадобитися створити деяку конфігурацію вручну, щоб підключити валідацію. Перегляньте довідник конфігурації Валідації .
Основи валідації
Найкращий спосіб зрозуміти валідацію - це побачити її в дії. Спочатку, припустимо, що ви створили звичайний PHP об'єкт, який вам потрібно використати у вашому додатку:
1 2 3 4 5 6 7
// src/Entity/Author.php
namespace App\Entity;
class Author
{
private string $name;
}
Поки це звичайний клас, який служить якійсь цілі всередині вашого додатку.
Задача валідації полягає в тому, щоб повідомити вам - чи є дані об'єкта
коректними (валідними). Для цього вам потрібно налаштувати перелік правил
(які називаються обмеження ), яким об'єкт
має відповідати, щоб бути валідним. Ці правила зазвичай визначаються з
використанням PHP-коду, але також можуть бути визначені як файли .yaml
або .xml
всередині каталогу config/validator/
:
Наприклад, для того, щоб гарантувати, що властивість $name
не порожня,
додайте наступний код:
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 string $name;
}
Додавання цієї конфігурації саме по собі ще не гарантує, що значення не буде порожнім; ви все ще можете встановити його як порожнє значення, якщо ви цього хочете. Щоб дійсно гарантувати, що значення доєднається до обмеження, об'єкт має бути переданий сервісу валідатора на перевірку.
Tip
Валідатор Symfony використовує рефлексію PHP, а такод методи "геттера", щоб отримати значення будь-якої властивості; вони можуть бути публичними, приватними або захищеними (див. ).
Використання сервісу валідаторa
Далі, щоб перевірити об'єкт Author
, використайте метод validate()
сервісу
validator
(який реалізує ValidatorInterface).
Обов'язки у validator
прості: прочитати обмеження (тобто правила) для класу
та визначити, чи відповідають дані з об'єкта цим обмеженням. Якщо валідація
проходить з помилкою, повертається список помилок (клас
ConstraintViolationList).
Давайте розглянемо цей простий приклад зсередини контролера:
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
// ...
use App\Entity\Author;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Validator\Validator\ValidatorInterface;
// ...
public function author(ValidatorInterface $validator): Response
{
$author = new Author();
// ... зрробити щось з обʼєктом $author
$errors = $validator->validate($author);
if (count($errors) > 0) {
/*
* Використовує метод __toString у змінній $errors, яка є об'єктом
* ConstraintViolationList. Это дает хорошую строку для отладки.
*/
$errorsString = (string) $errors;
return new Response($errorsString);
}
return new Response('The author is valid! Yes!');
}
Якщо властивість $name
порожнє, ви побачите наступне повідомлення
про помилку:
1 2
Object(App\Entity\Author).name:
Це значення не має бути порожнім.
Якщо ж ви вкажете значення для властивості name
, з'явиться повідомлення
про успішну валідацію.
Tip
У більшості випадків, ви не будете напряму взаємодіяти з сервісом
validator
і вам не потрібно буде турбуватися про відображення
помилок. Часто ви використовуватимете валідацію опосередковано при
обробці даних з відправлених додатку форм. Детальніше про це читайте тут:
як валідувати форми Symfony .
Ви також можете передати колекцію помилок у шаблон:
1 2 3 4 5
if (count($errors) > 0) {
return $this->render('author/validation.html.twig', [
'errors' => $errors,
]);
}
Всередині шаблону ви можете вивести список помилок так як вам потрібно:
1 2 3 4 5 6 7
{# templates/author/validation.html.twig #}
<h3>Автор має наступні помилки</h3>
<ul>
{% for error in errors %}
<li>{{ error.message }}</li>
{% endfor %}
</ul>
Note
Кожна помилка валідації (яка називається "порушенням обмеження") представляється
об'єктом ConstraintViolation. Цей об'єкт
дозволяє вам, серед іншого, отримати обмеження, яке спричинило це
порушення завдяки методу ConstraintViolation::getConstraint()
.
Викличні валідації
Validation
також дозволяє вам створювати замикання, щоб валідувати
значення у відповідності до набору обмежень (корисно, наприклад, при
валідації відповідей команд Консолі або
при валідації значень OptionsResolver ):
- createCallable()
-
Повертає замикання, яке викликає
ValidationFailedException
, коли обмеження не співпадають. - createIsValidCallable()
-
Викликає замикання, яке повертає
false
, коли обмеження не співпадають.
Обмеження
Validator
створений для того, щоб перевіряти об'єкти на відповідність
обмеженням (тобто правилам). Для того щоб валідувати об'єкт, просто вкажіть
для його класу одне або декілька обмежень та передайте його сервісу валідації
(validator
).
За лаштунками, обмеження - це просто PHP-об'єкт, який виконує ствердний вираз.
У реальному житті, обмеження може виглядати так: "пиріг не має згоріти"
. У
Symfony обмеження виглядають схоже: це твердження, що деяка умова є істиною.
Враховуючи значення, обмеження скаже вам, чи відповідає це значення правилам
обмеження.
Підтримувані обмеження
Symfony містить велику кількість найнеобхідніших обмежень:
Дата оновлення перекладу 2024-05-29
Базові обмеження
Це базові обмеження: використовуйте їх, щоб ствердити дуже базові речі про значення властивостей, або повернути значення методів у вашому обʼєкті.
Інші обмеження
- AtLeastOneOf
- Sequentially
- Compound
- Callback
- Expression
- When
- All
- Valid
- Cascade
- Traverse
- Collection
- Count
- UniqueEntity
- EnableAutoMapping
- DisableAutoMapping
Ви також можете створювати власні обмеження. Ця тема охоплена у статті Як створити користувацьке обмеження валідації.
Конфігурація обмежень
Деякі обмеження, як наприклад, NotBlank, прості,
у той час як інші, наприклад, Choice, мають декілька
опцій конфігурації. Припустимо, що клас Author
має властивість genre
(жанр), яка
визначає жанр літератури, який в основному асоціюється з автором, і яку можна встановити
у значення "художня" або "нон-фікшн" ("fiction" або "non-fiction"):
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 string $genre;
// ...
}
Опції обмеження завжди можуть бути передані у вигляді масиву. Однак, деякі
обмеження також дозволяють вам передавати значення однієї опції «за замовчуванням»
замість масиву. У випадку з обмеженням Choice
, опції choices
можна
вказати таким чином.
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 string $genre;
// ...
}
Така можливість дозволяє зробити налаштування найрозповсюдженіших опцій обмеження коротшим та швидшим.
Якщо ви не впевнені, як потрібно вказувати опцію, звіртеся з простором імен
Symfony\Component\Validator\Constraints
стосовно обмеження або ж вчиняйте
безпечно - завжди передавайте масив опцій (як продемонстровано у першому методі
вище).
Обмеження в класах форми
Обмеження можуть бути позначені під час побудови форм за допомогою опції
constraints
полів форми:
1 2 3 4 5 6 7 8 9
public function buildForm(FormBuilderInterface $builder, array $options): void
{
$builder
->add('myField', TextType::class, [
'required' => true,
'constraints' => [new Length(['min' => 3])],
])
;
}
Цілі обмеження
Обмеження можуть бути застосовані до властивості класу (наприклад, name
),
публічного геттер-методу (наприклад, getFullName()
) або цілому класу. Перший
вариіант найбільш розповсюджений та легкий. Однак обмеження геттера довзоляють
вам вказувати складніші правила валідації. І, нарешті, обмеження класу призначені
для випадків, коли ви хочете валідувати клас в якості одного цілого.
Властивості
Валідація властивостей класу - найпростіша техніка валідації. Symfony дозволяє
вам перевіряти приватні, захищені або публічні властивості. Нижче ви побачите,
як зробити так, щоб властивість $firstName
класу Author
мала як мімнімум
3 символи.
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 string $firstName;
}
Caution
Валідатор використовуватиме значення null
якщо ініціалізація типізованої властивості
була відмінена. Це може викликати неочікувану поведінку, якщо властивість містить значення
при ініціалізації. Щоб уникнути цього, переконайтеся, що всі властивості ініціалізовані до
їхньої валідації.
Гетери
Обмеження також можуть застосовуватися для того, щоб повернути значення методу. Symfony дозволяє вам додавати обмеження до будь-якого публічного методу, ім'я якого починається з «get», «is» або «has». У цій книзі подібні методи називаються загальним словом «гетери».
Перевагою цієї техніке є те, що вона дозволяє вам валідувати ваш об'єкт динамічно.
Наприклад, уявіть, що вам потрібно переконатися, що поле пароля не співпадає з
іменем користувача (з міркувань безпеки). Ви можете зробити це, створивши метод
isPasswordLegal()
та вказавши, що цей метод має повернутися як true
:
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(): bool
{
// ... return true or false
}
}
Тепер створіть метод isPasswordLegal()
та додайте його у потрібну вам логіку:
1 2 3 4
public function isPasswordSafe(): bool
{
return $this->firstName !== $this->password;
}
Note
Найуважніші з вас помітили, що префікс геттера («get», «is» або «has») опущено при відображенні. Це дозволить вам застосувати обмеження до властивості з таким же ім'ям пізніше (або навпаки), не змінюючи логіку валідації.
Класи
Деякі обмеження застосовуються до цілого валідованого класу. Наприклад, обмеження Callback (зворотний виклик) - це універсальне обмеження, яке застосовується до самого класу. Коли цей клас валідується, методи, вказані обмеженням, просто виконуються, що дозволяє проводити більш вибіркову валідацію.
Валідація обʼєкта з наслідуванням
Коли ви валідуєте об'єкт, який розширює інший клас, валідатор автоматично валідує обмеження, визначені у батьківському класі.
Обмеження, визначені у батьківських властивостях, будуть застосовані до дочірніх властивостей, навіть якщо властивості дочірнього класу перевизначають ці обмеження. Symfony завжди буде об'єднувати батьківські обмеження для кожної властивості.
Ви не можете змінити цю поведінку, але ви можете подолати її, визначивши батьківські і дочірні обмеження у різних групах валідації, а потім обирати відповідну групу під час валідації кожного об'єкта.
Налагодження обмежень
Використайте команду debug:validator
, щоб перерахувати обмеження валідації
даного класу:
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
-----------------------------------------------------
+---------------+--------------------------------------------------+---------------+------------------------------------------------------------+
| Властивість | Ім'я | Групи | Опції |
+---------------+--------------------------------------------------+---------------+------------------------------------------------------------+
| firstArgument | Symfony\Component\Validator\Constraints\NotBlank | за | [ |
| | | замовчуванням | "message" => "Це значення не має бути порожнім.", |
| | | | "allowNull" => false, |
| | | | "normalizer" => null, |
| | | | "payload" => null |
| | | | ] |
| firstArgument | Symfony\Component\Validator\Constraints\Email | за | [ |
| | | замовчуванням | "message" => "Це значення не валідна адреса email.", |
| | | | "mode" => null, |
| | | | "normalizer" => null, |
| | | | "payload" => null |
| | | | ] |
+---------------+--------------------------------------------------+---------------+------------------------------------------------------------+
Ви також можете валідувати всі класи, що зберігаються у даному каталозі:
1
$ php bin/console debug:validator src/Entity
Висновки
Validator
Symfony - це потужний інструмент, який використовується для отримання гарантій,
що дані деякого об'єкта "валідні". Сила валідації - в обмеженнях, які є правилами, які ви
можете застосувати до властивостей або геттер-методів вашого об'єкта. І незважаючи на те,
що ви більшою мірою використовуватимете фреймворк валідації опосередковано при використанні
форм, пам'ятайте, що він може бути використаний де завгодно для валідації будь-якого об'єкта.
Дізнайтеся більше
- Як створити користувацьке обмеження валідації
- Як застосувати лише підмножину усіх ваших обмежень валідації (групи валідації)
- Як валідувати необроблені значення (скалярні значення та масиви)
- Як послідовно застосовувати групи валідації
- Як обробляти різні рівні помилок
- Як перекладати повідомлення обмежень валідації