是否可以在configureOptions中动态设置data_class?
Is it possible to dynamically set data_class in configureOptions?
我正在尝试重构一些错误的代码,目前我有超过 20 个表单(字典),其中包含一个名为 name
的字段,以及两个类似的表单(字典),其中包含额外的字段。
这些表单作为集合嵌入到另一种表单中,其中 entry_type
根据从我的工厂返回的值动态设置为以前的表单之一。
目的是在编辑其他一些表单时修改选择,以便用户可以使用新的 button/delete 按钮自由添加或删除选项。
我试图通过创建一个包含单个字段的基本表单来删除我的 20 个表单 - name
并在 configureOptions
中动态配置 data_class
但我找不到这样做的方法。当我尝试修改构造函数并在那里设置值时,我无法在 createForm
期间访问构造函数 - 我只能传递选项,但在 configureOptions
.[= 中无法访问选项23=]
我通过 $this->createForm(new FormType($option))
发现在旧版本的 symfony 中是可能的
是否可以在 symfony 5 中做类似的事情?如果不是,解决方法是什么?
如果我能改进问题,请告诉我。这是代码:
操作:
/**
* @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()
]);
}
(想法)基本形式:
<?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,
]);
}
}
重复的示例表格。其他形式基本只有'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',
]);
}
}
家长形式:
<?php
namespace App\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\CollectionType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
class DictionaryCollectionType extends AbstractType {
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('dictionary', CollectionType::class, [
'entry_type' => $options['type'],
'entry_options' => array('label' => false),
'empty_data' => null,
'allow_add' => true,
'allow_delete' => true,
'label' => false,
])
->add('save', SubmitType::class, [
'attr' => ['class' => 'save btn btn-success mt-2', 'data-toggle' => 'modal', 'data-target' => '#dictionaryBackdrop', 'action' => $options['action']],
]);
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'data_class' => null,
'type' => null,
'action' => null
));
}
}
不要使用构造函数来传递配置选项,而只是使用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
格式。
我正在尝试重构一些错误的代码,目前我有超过 20 个表单(字典),其中包含一个名为 name
的字段,以及两个类似的表单(字典),其中包含额外的字段。
这些表单作为集合嵌入到另一种表单中,其中 entry_type
根据从我的工厂返回的值动态设置为以前的表单之一。
目的是在编辑其他一些表单时修改选择,以便用户可以使用新的 button/delete 按钮自由添加或删除选项。
我试图通过创建一个包含单个字段的基本表单来删除我的 20 个表单 - name
并在 configureOptions
中动态配置 data_class
但我找不到这样做的方法。当我尝试修改构造函数并在那里设置值时,我无法在 createForm
期间访问构造函数 - 我只能传递选项,但在 configureOptions
.[= 中无法访问选项23=]
我通过 $this->createForm(new FormType($option))
是否可以在 symfony 5 中做类似的事情?如果不是,解决方法是什么?
如果我能改进问题,请告诉我。这是代码:
操作:
/**
* @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()
]);
}
(想法)基本形式:
<?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,
]);
}
}
重复的示例表格。其他形式基本只有'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',
]);
}
}
家长形式:
<?php
namespace App\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\CollectionType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
class DictionaryCollectionType extends AbstractType {
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('dictionary', CollectionType::class, [
'entry_type' => $options['type'],
'entry_options' => array('label' => false),
'empty_data' => null,
'allow_add' => true,
'allow_delete' => true,
'label' => false,
])
->add('save', SubmitType::class, [
'attr' => ['class' => 'save btn btn-success mt-2', 'data-toggle' => 'modal', 'data-target' => '#dictionaryBackdrop', 'action' => $options['action']],
]);
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'data_class' => null,
'type' => null,
'action' => null
));
}
}
不要使用构造函数来传递配置选项,而只是使用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
格式。