预填充 EntityType 类型的 Symfony 表单的字段

Posted

技术标签:

【中文标题】预填充 EntityType 类型的 Symfony 表单的字段【英文标题】:Pre-filling a field of a Symfony form of type EntityType 【发布时间】:2021-11-30 22:49:54 【问题描述】:

我正在处理一个 Symfony 项目,我目前遇到了一个问题,我想从一组对象中预填充一个表单。

有问题的表单域的类型为 EntityType::class。我想从包含相同类型(Classe)对象的集合中预先选择该字段的元素。

我找到的一个解决方案是在 buildForm 中添加一个 'data' => $defaultClass 属性,该属性将包含要插入的数据,并在 formBuilder 的参数($options)中传递这个对象。 不幸的是,即使 $op​​tions 变量包含对象,一旦生成表单,这两个 Classe 类型的对象就不会出现在字段中。

提前感谢您的帮助。以下是相关代码:

搜索课程数据

<?php

  namespace App\Data;

  use App\Entity\Classe;
  use App\Entity\Teacher;
  use App\Entity\Location;

  class SearchCourseData

 /**
 * @var integer
 */
public $page = 1;

/**
 * @var Classe[]
 */
public $classe = [];

// Missing lines

/**
 * @var String
 */
public $status;

代码搜索课程表

class SearchCourseForm extends AbstractType 

public function buildForm(FormBuilderInterface $builder, array $options) 

    $defaultClass = new Classe();
    if (!empty($options['data']->classe)) 
        $defaultClass = $options["data"]->classe;
    

    $builder
            ->add('classe', EntityType::class, [
                'class' => Classe::class,
                'label' => false,
                'required' => false,
                'expanded' => false,
                'multiple' => true,
                'query_builder' => function (ClasseRepository $qb) 
                    return $qb->createQueryBuilder('a')->orderBy('a.title', 'ASC');
                ,
                'choice_label' => function (Classe $atelier) 
                    return($atelier->getTitle());
                ,
                'attr' => [
                    'placeholder' => 'Atelier',
                    'class' => 'select-classes'
                ],
                'data' => $defaultClass,
                
            ])
               >add('status', ChoiceType::class, [
                'required' => true,
                'choices' => [
                    'Disponible' => "Disponible",
                    'Brouillon' => "Brouillon",
                    'Archivé' => "Archivé"
                ],
                'label' => false,
            ])
    ;


public function configureOptions(OptionsResolver $resolver) 
    $resolver->setDefaults([
        'data_class' => SearchCourseData::class,
        'method' => 'GET',
        'csrf_protection' => false
    ]);
   


public function getBlockPrefix() 
    return '';



代码课程控制器

/**
 * @Route("/course")
 */
class CourseController extends AbstractController 

/**
 * @Route("/",name="course")
 */
public function courseList(CourseRepository $courseRepository, Request $request) 


        $data = new SearchCourseData();
        
        $defaultClassB = $this->getDoctrine()->getRepository(Classe::class)->find(49);
        $defaultClassA = $this->getDoctrine()->getRepository(Classe::class)->find(1);

        $defaultClass[] = new ArrayCollection();
        $defaultClass[0] = $defaultClassA;
        $defaultClass[1] = $defaultClassB;

        $data->classe = $defaultClass;

        
        $form = $this->createForm(SearchCourseForm::class, $data);
       


【问题讨论】:

第一个:从$defaultClass[] = new ArrayCollection();$defaultClass = new ArrayCollection(); 然后使用$defaultClass-&gt;add($defaultClassA); 在构造函数 public function __construct() $this-&gt;classe = new ArrayCollection(); 中添加 new ArrayCollection(); SearchCourseData 然后在控制器中添加 $defaultClassA = $this-&gt;getDoctrine()... $data-&gt;classe-&gt;add($defaultClassA);$data-&gt;classe-&gt;add($defaultClassB); 感谢您的留言,问题与表格的填充无关,而与buildform中表格的显示有关。您还有其他想法吗? 【参考方案1】:

@V-light 是对的,您正在数组的索引中设置一个集合 - 然后覆盖它...

$defaultClass[] = new ArrayCollection();
// === $defaultClass[0] = new ArrayCollection();

正确和最简单的方法是:

/**
 * @Route("/course")
 */
class CourseController extends AbstractController 

/**
 * @Route("/",name="course")
 */
public function courseList(CourseRepository $courseRepository, Request $request) 


        $data = new SearchCourseData();            
        $data->classe = $this->getDoctrine()->getRepository(Classe::class)->findById([49, 1]);

        $form = $this->createForm(SearchCourseForm::class, $data);
       


编辑 - 更正后的形式: 类的“数据”由 ModelTransformer 自动设置。

class SearchCourseForm extends AbstractType 

public function buildForm(FormBuilderInterface $builder, array $options) 

    $builder
            ->add('classe', EntityType::class, [
                'class' => Classe::class,
                'label' => false,
                'required' => false,
                'expanded' => false,
                'multiple' => true,
                'query_builder' => function (ClasseRepository $qb) 
                    return $qb->createQueryBuilder('a')->orderBy('a.title', 'ASC');
                ,
                'choice_label' => function (Classe $atelier) 
                    return($atelier->getTitle());
                ,
                'attr' => [
                    'placeholder' => 'Atelier',
                    'class' => 'select-classes'
                ],
                
            ])
               >add('status', ChoiceType::class, [
                'required' => true,
                'choices' => [
                    'Disponible' => "Disponible",
                    'Brouillon' => "Brouillon",
                    'Archivé' => "Archivé"
                ],
                'label' => false,
            ])
    ;


public function configureOptions(OptionsResolver $resolver) 
    $resolver->setDefaults([
        'data_class' => SearchCourseData::class,
        'method' => 'GET',
        'csrf_protection' => false
    ]);
   


【讨论】:

感谢您的回复,我已经进行了更改,但是这并不能解决问题,因为 $data->class 变量包含类并且表单确实收到了预期的类(SearchCourseForm 中的 $defaultClass ) 删除表单类型中的data - 这几乎不需要。这就是表单的工作方式 - 它将给定的数据类转换为表单。 即使我去掉表单中的数据选项,字段也不显示类,你能帮帮我吗? EntityType 中是否存在类?如果它们不存在,则无法选择它们。

以上是关于预填充 EntityType 类型的 Symfony 表单的字段的主要内容,如果未能解决你的问题,请参考以下文章

Wordpress用内容预填充主内容,限制为post类型

如何使用查询参数预填充单选按钮?

根据另一个表单字段(单选按钮)预填充值 HTML 表单输入

ASP.NET / 模型 - 防止模型预填充表单输入字段

如何防止 EntityType 在与同一实体(父)的多对一关系中显示当前对象?

开发将定义 .mdf 数据库的实体框架类