Як викоритовувати форму без класу даних
Дата оновлення перекладу 2024-05-27
Як викоритовувати форму без класу даних
У більшості випадків, форма привʼязана до обʼєкта, а поля форми отримують та зберігають свої дані у властивостях цього обʼєкта. Це саме те, про що йдеться мова у головній статті з форм.
Але іноді вам може знадобитися використати форму без класу і отримати назад
масив відправлених даних. Метод getData()
дозволяє вам робити саме це:
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
// src/Controller/ContactController.php
namespace App\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
// ...
class ContactController extends AbstractController
{
public function contact(Request $request): Response
{
$defaultData = ['message' => 'Type your message here'];
$form = $this->createFormBuilder($defaultData)
->add('name', TextType::class)
->add('email', EmailType::class)
->add('message', TextareaType::class)
->add('send', SubmitType::class)
->getForm();
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
// дані - це масив з ключами "name", "email", і "message"
$data = $form->getData();
}
// ... відобразити форму
}
}
За замовчуванням, форма насправді припускає, що ви хочете працювати з масивами даних, замість обʼєкта. Існує рівно два способи, щоб змінити цю поведінку та привʼязати форму до обʼєкта:
- Передати обʼєкт при створенні форми (в якості першого аргументу
createFormBuilder()
або другого аргументуcreateForm()
); - Оголосити у вашій формі опцію
data_class
.
Якщо ви не зробите нічого з цього, тоді форма буде повертати дані у вигляді
масиву. У цьому прикладі, так як $defaultData
- це не обʼєкт (і не встановлена
опція data_class
), $form->getData()
в кінцевому рахунку повертає масив.
Tip
Ви також можете отримати доступ до значень POST (у цьому випадку - "name") напряму через обʼєкт запиту, ось так:
1
$request->request->get('name');
Але майте на увазі, що у більшості випадків, використання методу getData()
буде краще, так як він повертає дані (зазвичай у вигляді обʼєкта) після того,
як вони були перетворені компонентом Форма.
Додавання валідації
Єдиним відсутнім елементом є валідація. Зазвичай, коли ви викликаєте
$form->handleRequest($request)
, обʼєкт валідується шляхом зчитування обмежень,
які ви застосували до цього класу. Якщо ваша форма привʼязана до обʼєкта (тобто,
ви використовуєте опцію data_class
або передаєте обʼєкт у вашу форму), то ви
захочете використовувати цей підхід майже завжди. Дивіться Валідація,
щоб дізнатися більше.
Але якщо форма не привʼязана до обʼєкта, і ви хочете отримати простий масив ваших відправлених даних, як ви можете додати обмеження до даних вашої форми?
Відповідь - встановити обмеження самостійно та приєднати їх до індивідуальних полів. Цей підхід детальніше розглядається у цій статті про валідацію, але ось короткий приклад:
Обмеження на рівні полів
Одна з можливостей - встановити обмеження самостійно і прикріпити їх до окремих полів. Загальний підхід більш детально описано у цій статті про валідацію, але ось короткий приклад:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Validator\Constraints\Length;
use Symfony\Component\Validator\Constraints\NotBlank;
public function buildForm(FormBuilderInterface $builder, array $options): void
{
$builder
->add('firstName', TextType::class, [
'constraints' => new Length(['min' => 3]),
])
->add('lastName', TextType::class, [
'constraints' => [
new NotBlank(),
new Length(['min' => 3]),
],
])
;
}
Tip
Якщо ви використовуєте групи валідації, вам потрібно або послатися на групу
Default
при створенні форми, або встановити правильну групу в обмеженні,
яке ви додаєте.
new NotBlank(['groups' => ['create', 'update']]);
Tip
Якщо форрма не привʼязана до обʼєкта, то кожний обʼєкт у вашому масиві
відправлених даних валідується з використанням обмеження
Symfony
, окрім випадків, коли
ви відключаєте валідацію.
Caution
Коли форма відправлена лише частково (наприклад, в HTTP-запиті PATCH), лише обмеження з відправлених полів форми будуть оцінені.
Обмеження на рівні класів
Інша можливість - додати обмеження на рівні класу.
Це можна зробити, встановивши опцію constraints
у методі
configureOptions()
:
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
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Validator\Constraints\Length;
use Symfony\Component\Validator\Constraints\NotBlank;
public function buildForm(FormBuilderInterface $builder, array $options): void
{
$builder
->add('firstName', TextType::class)
->add('lastName', TextType::class);
}
public function configureOptions(OptionsResolver $resolver): void
{
$constraints = [
'firstName' => new Length(['min' => 3]),
'lastName' => [
new NotBlank(),
new Length(['min' => 3]),
],
];
$resolver->setDefaults([
'data_class' => null,
'constraints' => $constraints,
]);
}
Це означає, що ви також можете зробити це при використанні методу createFormBuilder()
у вашому контролері :
1 2 3 4 5 6 7 8 9 10 11 12
$form = $this->createFormBuilder($defaultData, [
'constraints' => [
'firstName' => new Length(['min' => 3]),
'lastName' => [
new NotBlank(),
new Length(['min' => 3]),
],
],
])
->add('firstName', TextType::class)
->add('lastName', TextType::class)
->getForm();