多年后我又回到了 Symfony,我很喜欢这个新版本 7。
我正在努力使用 CollectionType,因为我只需要显示基于主对象的某些字段,但我找不到将参数/选项传递到嵌入表单(CollectionType)的方法。
如果我传递额外的选项,我会收到错误:
An error has occurred resolving the options of the form "Symfony\Component\Form\Extension\Core\Type\CollectionType": The option "category" does not exist.
我有一个基于“活动”实体的表单,并且活动可以有许多动物。 根据活动的类别,动物应该有一些领域,而不是其他领域。
我的想法是将活动的类别传递给子表单,并在那里编写逻辑以添加所需的字段。
怎样才能做到这一点?
这是我的代码:
<?php
namespace App\Form;
use App\Entity\Activity;
use App\Entity\ActivityCategory;
use App\Entity\Animal;
use App\Entity\User;
use App\Form\ActivityAnimalType;
use Symfony\Component\Form\Extension\Core\Type\CollectionType;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
class ActivityType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options): void
{
$builder
->add('date')
->add('shift')
->add('people', EntityType::class, [
'class' => User::class,
'multiple' => true,
])
->add('animals', CollectionType::class, [
'entry_type' => AnimalType::class,
'entry_options' => [
'label' => false,
],
'category' => $options['category'],
'allow_add' => true,
'allow_delete' => true,
'by_reference' => false,
])
->add('save', SubmitType::class);
;
if ($options['category'] == 'asilo') {
$builder->remove('people');
}
}
public function configureOptions(OptionsResolver $resolver): void
{
$resolver->setDefaults([
'data_class' => Activity::class,
'category' => ActivityCategory::class,
]);
}
}
还有AnimanType
<?php
namespace App\Form;
use App\Entity\Activity;
use App\Entity\ActivityAnimal;
use App\Entity\Animal;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
class AnimalType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options): void
{
$builder
->add('quantity')
->add('type', ChoiceType::class, [
'choices' => [
'Full Day' => 1,
'Half Day' => 2,
],
])
;
}
public function configureOptions(OptionsResolver $resolver): void
{
$resolver->setRequired(['category']);
$resolver->setDefaults([
'data_class' => ActivityAnimal::class,
]);
}
}
虽然将 Activity->category 从控制器传递到主窗体效果很好,但我找不到在嵌入式 CollectionType 中插入相同逻辑的方法。
我尝试将选项传递给 CollectionType,并查看了文档中的所有位置。 我也查看了事件监听器,但没有找到类似的案例。
谢谢!
有两件事:
-> 如前所述,“类别”不作为选项存在:) 查看此处的文档。 因此,如果您想在表单上添加类别,您可以添加一个属性(“attr”选项)。
-> 如果您需要搜索数据以获取您选择的类别的动物,您必须在控制器上执行此操作并在选项中传递数据。
例如,在您的控制器中:
$animalCollection = $em->getRepository(Animal::class)->findBy(['category' => $category]);
$form = $this->createForm(ActivityType::class, $activity, ['category' => $category, 'animal_collection' => $animalCollection]);
以您的形式:
<?php
namespace App\Form;
use App\Entity\Activity;
use App\Entity\ActivityCategory;
use App\Entity\Animal;
use App\Entity\User;
use App\Form\ActivityAnimalType;
use Symfony\Component\Form\Extension\Core\Type\CollectionType;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
class ActivityType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options): void
{
$builder
->add('date')
->add('shift')
->add('people', EntityType::class, [
'class' => User::class,
'multiple' => true,
])
->add('animals', CollectionType::class, [
'entry_type' => AnimalType::class,
'entry_options' => [
'label' => false,
],
// If you need to keep your category as an attribute in you form
'attr' => ['category' => $options['category']],
// Datas from your controller
'data' => $option['animal_collection'],
'allow_add' => true,
'allow_delete' => true,
'by_reference' => false,
])
->add('save', SubmitType::class);
;
if ($options['category'] == 'asilo') {
$builder->remove('people');
}
}
public function configureOptions(OptionsResolver $resolver): void
{
$resolver->setDefaults([
'data_class' => Activity::class,
'category' => null,
'animal_collection' => null,
]);
}
}
希望这些对你有帮助。