Створення користувацького вгадувача типу
Дата оновлення перекладу 2023-09-07
Створення користувацького вгадувача типу
Компонент Form може вгадувати тип та деякі опції поля форми, використовуючи вгадувачі типу. Компонент вже містить у собі відгадувач типу, використовуючи ствердження компонента Validation, але ви також можете додавати ваші користувацькі вгадувачі типу.
Вгадувачі використовуються лише в наступних випадках:
- Використавши createForProperty() або createBuilderForProperty();
- Викликавши add() або create() або add() без ясного типу, в контексті, де батьківська форма має визначений клас даних.
Створіть вгадувач типу PHPDoc
У цьому розділі ви побудуєте вгадувач, який читає інформацію про поля з властивостей PHPDoc. Спочатку, вам потрібно створити клас, що реалізує FormTypeGuesserInterface. Цей інтерфейс вимагає чотири методи:
- guessType()
- Намагається вгадати тип поля;
- guessRequired()
- Намагається вгадати значення обовʼязкової опції;
- guessMaxLength()
-
Намагається вгадати значення атрибуту введення
maxlength
; - guessPattern()
-
Намагається вгадати значення атрибуту введення
pattern
.
Почніть зі створення класу та цих методів. Далі, ви дізнаєтеся, як заповнювати кожний з них:
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
// src/Form/TypeGuesser/PHPDocTypeGuesser.php
namespace App\Form\TypeGuesser;
use Symfony\Component\Form\FormTypeGuesserInterface;
use Symfony\Component\Form\Guess\TypeGuess;
use Symfony\Component\Form\Guess\ValueGuess;
class PHPDocTypeGuesser implements FormTypeGuesserInterface
{
public function guessType(string $class, string $property): ?TypeGuess
{
}
public function guessRequired(string $class, string $property): ?ValueGuess
{
}
public function guessMaxLength(string $class, string $property): ?ValueGuess
{
}
public function guessPattern(string $class, string $property): ?ValueGuess
{
}
}
Вгадування типу
При вгадуванні типу, метод повертає або екземпляр класу TypeGuess, або нічого, щоб визначити, що вгадувач не може вгадати тип.
Конструктор TypeGuess
вимагає три опції:
- Імʼя типу (один з типів форми);
- Додаткові опції (наприклад, коли тип -
entity
, вам також потрібно встановити опціюclass
). Якщо не вгадано жодний тип, вони повинні бути встановлені як порожній масив; - Впевненість у тому, що вгаданий тип - вірний. Це може бути однією з
констант класу Guess:
LOW_CONFIDENCE
,MEDIUM_CONFIDENCE
,HIGH_CONFIDENCE
,VERY_HIGH_CONFIDENCE
. Після того, як будуть виконані усі вгадувачі типу, буде використано тип з набільшою довірою.
Знаючи це, ви можете з легкістю реалізувати метод guessType()
у PHPDocTypeGuesser
:
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 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52
// src/Form/TypeGuesser/PHPDocTypeGuesser.php
namespace App\Form\TypeGuesser;
use Symfony\Component\Form\Extension\Core\Type\CheckboxType;
use Symfony\Component\Form\Extension\Core\Type\IntegerType;
use Symfony\Component\Form\Extension\Core\Type\NumberType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\Guess\Guess;
use Symfony\Component\Form\Guess\TypeGuess;
class PHPDocTypeGuesser implements FormTypeGuesserInterface
{
public function guessType(string $class, string $property): ?TypeGuess
{
$annotations = $this->readPhpDocAnnotations($class, $property);
if (!isset($annotations['var'])) {
return null; // нічого не вгадувати, якщо анотація @var не доступна
}
// в іншому випадку, засновуйте тип на анотації @var
return match($annotations['var']) {
// існує висока впевненість у тому, що тип - текст, коли
// використовується рядок @var
'string' => new TypeGuess(TextType::class, [], Guess::HIGH_CONFIDENCE),
// цілі числа також можуть бути id сутності або кнопкою-прапорцем (0 або 1)
'int', 'integer' => new TypeGuess(IntegerType::class, [], Guess::MEDIUM_CONFIDENCE),
'float', 'double', 'real' => new TypeGuess(NumberType::class, [], Guess::MEDIUM_CONFIDENCE),
'boolean', 'bool' => new TypeGuess(CheckboxType::class, [], Guess::HIGH_CONFIDENCE),
// впевненість у тому, що цей тип правильний, дуже низька
default => new TypeGuess(TextType::class, [], Guess::LOW_CONFIDENCE)
};
}
protected function readPhpDocAnnotations(string $class, string $property): array
{
$reflectionProperty = new \ReflectionProperty($class, $property);
$phpdoc = $reflectionProperty->getDocComment();
// парувати $phpdoc у масив таким чином:
// ['var' => 'string', 'since' => '1.0']
$phpdocTags = ...;
return $phpdocTags;
}
// ...
}
Цей вгадувач типу тепер може вгадувати тип поля для властивості, якщо вона має PHPdoc!
Опції поля вгадування
Три інших методи (guessMaxLength()
, guessRequired()
і guessPattern()
)
повертають екземпляр ValueGuess зі значенням
опції. Цей конструктор має 2 аргументи:
- Значенея опції;
- Впевненість у тому, що вгадане значення - вірне (використовуючи константи
класу
Guess
).
null
вгадується, коли ви думаєте, що значення опції не має бути
встановленим.
Caution
Ви маєте бути дуже обережні, використовуючи метод guessMaxLength()
. Коли тип - float,
ви не можете визначити довжину (наприклад, ви хочете, щоб float був менше, ніж 5
,
54.512313
- не є валідним, але length(5.512314) > length(5)
- валідно, так що схема
спрацює). У цьому випадку, значення повинно бути встановлене як null
з MEDIUM_CONFIDENCE
.
Реєстрація вгадувача типу
Якщо ви використовуєте автомонтування та автоконфігурацію , то ви закінчили! Symfony вже знає та використовує ваш вгадувач типу форми.
Якщо ви не використовуєте автомонтування та автоконфігурацію, зареєструйте ваш
сервіс вручну та тегуйте його за допомогою form.type_guesser
:
1 2 3 4 5 6
# config/services.yaml
services:
# ...
App\Form\TypeGuesser\PHPDocTypeGuesser:
tags: [form.type_guesser]
Tip
Виконайте наступну команду, щоб верифікувати, що вгадувач типу форми був успішно зареєстрований у додатку:
1
$ php bin/console debug:form