为了账号安全,请及时绑定邮箱和手机立即绑定

Symfony 4 - Forms CollectionType 获取特定数据

Symfony 4 - Forms CollectionType 获取特定数据

PHP
红颜莎娜 2022-01-08 20:17:13
我有两种实体:“Affaire”和“Pointage”。我的 Affaire Entity 与我的 Pointage Entity 有 OneToMany 关系://App\Entity\Affaire.php/** * @ORM\OneToMany(targetEntity="App\Entity\Pointage", mappedBy="numAffaire") */    private $pointages;//App\Entity\Pointage.php/** * @ORM\ManyToOne(targetEntity="App\Entity\Affaires", inversedBy="pointages") * @ORM\JoinColumn(nullable=false) */    private $numAffaire;我为我的 Affaire 实体创建了一个表格,该表格获得与“Affaire”相关的“Pointages”。//App\Form\AffaireType.phpclass AffaireType extends AbstractType{    public function buildForm(FormBuilderInterface $builder, array $options)    {        $builder->add('numAffaire');        $builder->add('descAffaire');        $builder->add('pointages', CollectionType::class, [            'entry_type' => PointageType::class,            'entry_options' => ['label' => false, 'pointages' => $options['pointages']],        ]);    }    public function configureOptions(OptionsResolver $resolver)    {        $resolver->setRequired(['pointages']);        $resolver->setDefaults([            'data_class' => Affaires::class,        ]);    }}//App\Form\PointageType.phpclass PointageType extends AbstractType{    public function buildForm(FormBuilderInterface $builder, array $options)    {        $builder->add('heurePointage');    }    public function configureOptions(OptionsResolver $resolver)    {        $resolver->setRequired(['pointages']);        $resolver->setDefaults([            'data_class' => Pointage::class,        ]);    }}我的问题是:如何过滤我的 AffaireType 类中的“Pointages”?例如,我想获取与我的 Affaire 关联的所有积分,其中我的积分的 id 小于 100。是否可以在某处进行查询?
查看完整描述

1 回答

?
胡子哥哥

TA贡献1825条经验 获得超6个赞

!!!我强烈建议您不要在那里做什么!

原因:

您的表单类型的数据类设置为实体(据我所知)。并且表单旨在修改给定的对象(您的实体)。现在,如果您过滤该表单类型的字段,然后表单尝试设置“新”值,Pointage则可能会删除所有不在表单提交中的对象(特别是所有被过滤掉的对象)。如果表单调用,您将丢失数据- 我不太确定,是否总是调用它,即使/设置为 false。如果你忘记了,这会让你的生活变得悲惨。我相信这总是被称为标准。setPointagesallow_addallow_removeCollectionType

阅读一些代码后更新:关于调用setPointages:如果addPointage/removePointage存在,它们将被调用。但是,PropertyAccessor(属性访问组件)从目标对象(!)读取先前的值,并且将计算差异并相应地调用 add/remove -> 删除不在新集合中的任何实体

可能的解决方法

  • 大量使用数据映射器/数据转换器/表单事件以某种方式隐藏存在更多Pointage实体的事实。这可能工作很好,但它使事情复杂化了很多,但仍然可能成为一个干净的解决方案。

    总体思路是:

    但是,您可能必须花费大量时间了解表单组件的内部结构才能正确安全地执行此操作……(一个指针MergeCollectionListener是看一下ResizeFormListener,它根据给定的数据添加和删除子表单。请记住,如果您过滤数据,您可能应该创建自己的集合类型并添加一个新的表单侦听器来优雅地处理所有内容)

    • 表单渲染:从实体获取(事务,所有积分)->您的转换器/映射器/表单事件处理程序(事务,所有->过滤积分)->表单(事务,过滤积分)

    • 表单提交:表单(事务,过滤点)->您的转换器/映射器/表单事件处理程序(事务,过滤->“新所有”点)->设置实体(事务,所有点)

  • 代替这种整合入AffaireType,添加另一种形式类型AffairePointageType具有两个字段:affaireAffaireTypepointages)和pointagesCollectionType),并调用它像

$filteredPointages = someFilterFunction($affaire->getPointages());

$this->createForm(AffairePointageType::class, [

     'affaire' => $affaire,

     'pointages' => $filteredPointages,

], [

     'pointages' => ... //the option you provide for the CollectionType

]);

  • 显然,您可以提供任何积分,由您喜欢的任何过滤器过滤,并且只会编辑您提供的那些,而保留与其他任何相关联的内容$affaire不变。但是请注意,您必须自己处理添加或删除的积分。(这可能会破坏关注点分离)

    本质上,这是以前解决方法的一个更易于理解的版本,其中所有过滤器逻辑都是外部的,但是由于表单没有传达“您可以编辑事务的积分”,而是“您可以同时编辑事务和一组可能相关或不相关的点数”,它在语义上很清楚,并且不会让未来的用户(包括您在内)感到惊讶。

但是,我相信您的方法可能存在缺陷……但是由于不清楚您实际要达到的目标,因此很难提出适当的解决方案。

如果只是“显示的(子)表单太多” - 那么它更多的是显示问题,可以并且可能应该通过 javascript 或 css ( display:none) 或两者来修复。(这是恕我直言更好的方法,不会与表单逻辑和/机制混淆)。


查看完整回答
反对 回复 2022-01-08
  • 1 回答
  • 0 关注
  • 134 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信