Symfony 2 - 为 EntityType 定义选定的值

Posted

技术标签:

【中文标题】Symfony 2 - 为 EntityType 定义选定的值【英文标题】:Symfony 2 - Define selected value for EntityType 【发布时间】:2022-01-02 03:29:19 【问题描述】:

我从事 Symfony 2.8 项目。该系统适用于 TextType / DateTimeType / MoneyType 但也不适用于 EntityType 和 DateType。

我尝试从会话中的值定义我的 EntityType 的默认值,该值在我在 Controller 中创建表单时传入参数,如下所示:

$filter_form = $this->createForm(FilterActeType::class, null, [
        'filters' => array_merge(
            $defaultFilter,
            $paginatorService->getFiltersFromSessionByContext($usr->getId(), $request->attributes->get('_route'))
        )
    ]);

我曾尝试在 EntityType 中使用 datachoice_value 参数,但问题是一样的:当我重新加载页面时,数据在变量会话中时表单过滤器中不存在数据。

数据参数不带匿名函数的情况:

$builder->add('etude', EntityType::class, [
            'label' => $this->translator->trans('Étude'),
            'class' => Etude::class,
            'required'  => false,
            'attr' => array('dyn-form-data' => 'cabinet,createur,destinataire'), // Champs dynamique => on renseigne le ou les enfants (le(s) champ(s) qui doit être mise à jour à la modification de celui-ci)
            'data' => $this->getDataFromFilters($options, 'etude'),
        ]);

观察:这个案例已经返回了一个错误信息:“...传递给选择字段必须被管理。也许你忘记在实体管理器中持久化它?”。

带有匿名函数的数据参数的情况:

$builder->add('etude', EntityType::class, [
            'label' => $this->translator->trans('Étude'),
            'class' => Etude::class,
            'required'  => false,
            'attr' => array('dyn-form-data' => 'cabinet,createur,destinataire'), // Champs dynamique => on renseigne le ou les enfants (le(s) champ(s) qui doit être mise à jour à la modification de celui-ci)
            'data' => function (EntityRepository $er) use ($options) 
                if (null != $etude = $this->getDataFromFilters($options, 'etude')) 
                    $er->createQueryBuilder('e')->andWhere('e.id = :id')->setParameter('id', $etude->getId());
                
            
        ]);

Observations:: 没有错误返回但也没有数据。

带有choice_value参数的情况:

$builder->add('etude', EntityType::class, [
            'label' => $this->translator->trans('Étude'),
            'class' => Etude::class,
            'required'  => false,
            'attr' => array('dyn-form-data' => 'cabinet,createur,destinataire'), // Champs dynamique => on renseigne le ou les enfants (le(s) champ(s) qui doit être mise à jour à la modification de celui-ci)
            'choice_value' => function() use ($options) 
                return $this->getDataFromFilters($options, 'etude');
            ,
        ]);

观察:没有错误返回,也没有数据。

Form对象中getDataFromFilters方法的代码:

/**
 * @param array $filters
 * @param string $field
 *
 * @return \DateTime|Etude|Cabinet|string|int|float|TypeDocument|ModeDistribution|null
 */
private function getDataFromFilters(array $options, string $field)

    return (isset($options['filters'][$field]) && (null != $value = $options['filters'][$field])) ? $value : null;

编辑(2021 年 11 月 24 日):添加了调试

这是存储在会话中的实体的调试:

etude: Etude #812 ▼
+__isInitialized__: true
-id: 1
-libelle: "Toto"
-mail: "yolo.toto@toto-france.fr"
-origines: PersistentCollection #811 ▼
  -snapshot: []
  -owner: null
  -association: null
  -em: null
  -backRefFieldName: null
  -typeClass: null
  -isDirty: false
  #collection: ArrayCollection #810 ▼
    -elements: []
  
  #initialized: false

-utilisateurs: PersistentCollection #809 ▼
  -snapshot: []
  -owner: null
  -association: null
  -em: null
  -backRefFieldName: null
  -typeClass: null
  -isDirty: false
  #collection: ArrayCollection #808 ▼
    -elements: []
  
  #initialized: false

-cabinets: PersistentCollection #807 ▼
  -snapshot: []
  -owner: null
  -association: null
  -em: null
  -backRefFieldName: null
  -typeClass: null
  -isDirty: false
  #collection: ArrayCollection #806 ▼
    -elements: array:1 [▼
      0 => Cabinet #805 ▼
        -id: 1
        -libelle: "Cabinet Toto"
        -etude: Etude #812 …2
        -infoUserByEtude: PersistentCollection #804 ▼
          -snapshot: []
          -owner: null
          -association: null
          -em: null
          -backRefFieldName: null
          -typeClass: null
          -isDirty: false
          #collection: ArrayCollection #803 ▼
            -elements: []
          
          #initialized: false
        
        -adresse: null
        -villeCP: null
      
    ]
  
  #initialized: true

-actes: PersistentCollection #802 ▼
  -snapshot: []
  -owner: null
  -association: null
  -em: null
  -backRefFieldName: null
  -typeClass: null
  -isDirty: false
  #collection: ArrayCollection #801 ▼
    -elements: []
  
  #initialized: false

-typeDocuments: PersistentCollection #800 ▼
  -snapshot: []
  -owner: null
  -association: null
  -em: null
  -backRefFieldName: null
  -typeClass: null
  -isDirty: false
  #collection: ArrayCollection #799 ▼
    -elements: []
  
  #initialized: false

-modeDistributions: PersistentCollection #798 ▼
  -snapshot: []
  -owner: null
  -association: null
  -em: null
  -backRefFieldName: null
  -typeClass: null
  -isDirty: false
  #collection: ArrayCollection #797 ▼
    -elements: []
  
  #initialized: false

-themeMainColor: null
-themeAccentColor: null
-logo: null
-background: null
-sous_domaine: "yolo"
-transactions: PersistentCollection #794 ▼
  -snapshot: []
  -owner: null
  -association: null
  -em: null
  -backRefFieldName: null
  -typeClass: null
  -isDirty: false
  #collection: ArrayCollection #795 ▼
    -elements: []
  
  #initialized: false

-templates: PersistentCollection #796 ▼
  -snapshot: []
  -owner: null
  -association: null
  -em: null
  -backRefFieldName: null
  -typeClass: null
  -isDirty: false
  #collection: ArrayCollection #138 ▼
    -elements: []
  
  #initialized: false

-aliasMail: "contact@toto-france.fr"
-smsActif: false
-notificationSmsActif: false
-paiementActif: true
-blocNoteActif: false
-connexionDirecteActif: false
-dureeTokenConnexionDirecte: 2
-smsSenderName: null
-locale: null
-faxActif: false
-dossierDebiteurActif: true
-defaultModuleActif: true
-frequenceNotification: "day"
-objetMail: null
-lienRgpd1: null
-lienRgpd2: null
-mailEchecNotification: null
 …2

【问题讨论】:

【参考方案1】:

使用 Symfony/PHP:

看看这个答案,希望它适用于您使用的版本,我相信是因为它说它是在 2.7 版本上添加的: https://***.com/a/35941528/17089665

使用 JS:

您可以发送一个变量,即使它存储在当前会话中,但您应该在您的controller 中发送。当您创建 form 时,您可以在渲染函数中发送变量。

通常情况下,您将发送一个您要制作表单的类的对象作为参数。我建议您使用Entity 的设置器来获取预定义值。

所以...一个简单的例子,如果你想显示一个下拉列表:

AppleController 用于创建一盒苹果:

$arrayOfTypes = however_you_get_your_info(); // <- With different types of apples
$newAppleBox = new AppleBox();
$newAppleBox->setWhateverVariableWithPredefinedValue() // Here, for example, if you were to create a modifyUserInfo template or something like this, you could prepopulate this with the current info so they don't need to write everything again.
$form = $this->createForm(AppleRegistrationType::class, $newAppleBox);

if ($form->isSubmitted() && $form->isValid()) 
// blablabla


return $this->render('registrations/appleBox.html.twig', [
        'appleBoxRegistrationForm' => $form->createView(),
        'typesArray' => $arrayOfTypes
]);

然后,在您的表单中,您通常会创建您的EntityType

use App\Entity\User;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
// ...

$builder->add('users', EntityType::class, [
    'class' => User::class,
     blablabla
]);

最后,在您的模板中,您可以使用twigjs 动态检索该列表并将其放入您的新&lt;select&gt;(我相信这是EntityType 在HTML 中被引用的内容)。

另外,看看官方文档:

https://symfony.com/doc/current/reference/forms/types/entity.html#using-choices

【讨论】:

以上是关于Symfony 2 - 为 EntityType 定义选定的值的主要内容,如果未能解决你的问题,请参考以下文章

选中 Symfony 表单 EntityType 复选框

如何使用 EntityType 字段对 Symfony 4 表单进行单元测试

Symfony - 使用重复的 EntityType 优化表单

Symfony Forms EntityType 使用 JS 全选

Symfony 表单 - EntityType 通过实体 ID 选择选项

Symfony sonata EntityType 编辑表单 - 选择 - 获取其他当前