是否可以在 configureOptions 中动态设置 data_class?

时间:2021-07-28 10:57:10

标签: forms symfony inheritance symfony-forms symfony5

我正在尝试重构一些糟糕的代码,目前我有 20 多个表单(词典),其中一个字段名为 if (BarCode.Contains(";")) { int cont = 0; List<string> list = BarCode.Split(';').ToList(); List<string> list2 = OBS.Split(';').ToList(); List<string> list3 = OBS2.Split(';').ToList(); int sizeList1 = list.Count; int sizeList2 = list2.Count; int sizeList3 = list3.Count; if (sizeList1 == sizeList2 && sizeList1 == sizeList3) { foreach (string l in list) { cont = +1; Etiqueta = l; OBSm = list2[cont]; OBS2m = list3[cont]; this.Print(printerName, this.PrintMultiples); } } } ,还有两个类似的表单(词典)带有额外的字段。

这些表单作为集合嵌入到另一种表单中,其中 name 会根据我的工厂返回的值动态设置为前一种表单。

目的是在编辑其他一些表单时修改选择,以便用户可以自由添加或删除带有新按钮/删除按钮的选项。

我尝试通过创建一个包含单个字段 entry_type 的基本表单并在 name 中动态配置 data_class 来删除我的 20 个表单,但我找不到方法去做。当我尝试修改构造函数并在那里设置值时,我无法在 configureOptions 期间访问构造函数 - 我只能传递选项,但在 createForm 中无法访问选项。

我发现通过 configureOptions

在旧版本的 symfony 中是可能的

是否可以在 symfony 5 中做类似的事情?如果没有,有什么解决方法?

如果我可以改进问题,请告诉我。代码如下:

操作:

$this->createForm(new FormType($option))

(的想法)基本形式:

/**
 * @Route("/dictionary/getForm/{id}",
 *     name="dictionary_form")
 * @param $id
 */    
public function getDictionaryView(Request $request, EntityManagerInterface $em, $id){

    $repository = $em->getRepository('App:'.substr($id, 3));
    $items = $repository->findAll();
    
    $form = $this->createForm(DictionaryCollectionType::class,['dictionary' => $items],array(
        'type' => DictionaryFormFactory::createForm($id),
        'action' => $id,
    ));

    $form->handleRequest($request);

    if($form->isSubmitted() && $form->isValid()){

        $data = $form->getData()['dictionary'];
        $idsForm = array_map(function($item) {return $item->getId();},$data);
        foreach($items as $item) {
            if(!in_array($item->getId(),$idsForm)) $em->remove($item);
        }

        foreach($data as $entity) {
            $em->persist($entity);
        }

        $em->flush();

        $return = [];
        foreach($data as $entity) {
            $append = ['value' => $entity->getId(), 'name' => $entity->getName()];
            if($entity instanceof DegreesDisciplines) $append['field'] = $entity->getField()->getId();
            $return[] = $append;
        }

        return new JsonResponse($return);

    }

    return $this->render('Admin\Contents\dictionary.html.twig', [
        'form' => $form->createView()
    ]);
}

重复的示例形式。基本上只有 'data_class' 其他形式的变化:

<?php

namespace App\Form\Dictionaries;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Form\Extension\Core\Type\TextType;

class NewDictionaryType extends AbstractType {

    private $data_class;

    public function __construct($data_class)
    {
        $this->data_class = $data_class;
    }
    
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder->add('name', TextType::class, [
            'label' => 'Nazwa',
        ]);
    }

    /**
     * @param OptionsResolver $resolver
     */
    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults([
            'data_class' => $this->data_class,
        ]);
    }
}

父表单:

<?php

namespace App\Form\Dictionaries;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Form\Extension\Core\Type\TextType;

class NewNoticesTypeType extends AbstractType {
    
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder->add('name', TextType::class, [
            'label' => 'Nazwa',
            'required' => false,
        ]);
    }

    /**
     * @param OptionsResolver $resolver
     */
    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults([
            'data_class' => 'App\Entity\NoticesTypes',
        ]);
    }
}

1 个答案:

答案 0 :(得分:1)

不要使用构造函数来传递配置选项,而只是使用 createForm 来传递选项:

$form = $this->createForm(DictionaryCollectionType::class,['dictionary' => $items],array(
    'type' => DictionaryFormFactory::createForm($id),
    'action' => $id,
    'data_class' => $dataClass // <-- put your data class (FQCN) here
));

请参阅 Symfony 关于 Passing Options to Forms

的文档

您可能应该重构的另一件事是 'App:'.substr($id, 3)。最好使用 FQCN 而不是旧的 Bundle:Entity 格式。