Как встраивать формы
Дата обновления перевода 2023-09-07
Как встраивать формы
Зачастую вам может захотеться построить форму, которая будет включать поля из
многих разных объектов. Например, форма регистрации может содержать данные,
принадлежащие объекту User
, а также многие объекты Address
. К счастью,
это просто и природно с помощью компонента формы.
Встраивание одного объекта
Представьте, что каждый Task
принадлежит простому объекту Category
. Начните,
конечно же, с создания объекта Category
:
1 2 3 4 5 6 7 8 9 10
// src/Entity/Category.php
namespace App\Entity;
use Symfony\Component\Validator\Constraints as Assert;
class Category
{
#[Assert\NotBlank]
public string $name;
}
Далее, добавьте новое своейство category
к классу Task
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
// ...
class Task
{
// ...
#[Assert\Type(type: Category::class)]
#[Assert\Valid]
protected ?Category $category = null;
// ...
public function getCategory(): ?Category
{
return $this->category;
}
public function setCategory(?Category $category): void
{
$this->category = $category;
}
}
Tip
Ограничение Valid
было добавлено к свойству category
. Это создаёт каскадное
включение валидации в соответствующую сущность. Если вы опустите это ограничение, то
дочерняя сущность не будет валидирована.
Теперь, когда ваше приложение было обновлено так, чтобы отображать новые
требование, создайте класс формы так, чтобы объект Category
можно было
изменять пользователю:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
// src/Form/CategoryType.php
namespace App\Form;
use App\Entity\Category;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
class CategoryType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options): void
{
$builder->add('name');
}
public function configureOptions(OptionsResolver $resolver): void
{
$resolver->setDefaults([
'data_class' => Category::class,
]);
}
}
Конечная цель - позволить Category
класса Task
подвергаться изменениям
прямо внутри формы задачи. Чтобы достигнуть этого, добавьте поле category
к объекту TaskType
, тип которого - экземпляр нового класса CategoryType
:
1 2 3 4 5 6 7 8 9
use Symfony\Component\Form\FormBuilderInterface;
use App\Form\CategoryType;
public function buildForm(FormBuilderInterface $builder, array $options)
{
// ...
$builder->add('category', CategoryType::class);
}
Поля изCategoryType
теперь могут быть отбражены на ряду с полями из
класса TaskType
.
Отобразите поля Category
таким же образом, как оргиниальные поля Task
:
1 2 3 4 5 6 7 8
{# ... #}
<h3>Category</h3>
<div class="category">
{{ form_row(form.category.name) }}
</div>
{# ... #}
Когда пользователь отправляет форму, отправленные данные для полей Category
используются для создания сущности Category
, которая потом устанавливается
в поле category
экземпляра Task
.
К экземпляр Category
можно получить доступ через $task->getCategory()
и
его можно сохранить в DB или использовать так, как вам это нужно.
Встраивание коллекции форм
Вы также можете встроить коллекцию форм в одну форму (представьте форму
Category
со многими подформами Product
). Это делается путём использования
типа поля collection
.
Чтобы узнать больше, смотрите статью Как встроить коллекцию форм и справочник CollectionType.