首页 > 解决方案 > EntityType 的 Symfony 禁用选项

问题描述

假设我有一个competence与该 entity 相关的 ManyToMany 实体location。此外,有些人users只能访问一个位置。

现在想象以下场景:能力FirstHelp与位置BerlinMunich. 用户Bob可以访问 location BerlinBob现在想编辑FirstHelp。应该允许他删除或添加 和 之间的关系FirstHelpBerlin但不应允许他触摸关系FirstHelp<=> Munich。他也不应该允许添加像FirstHelp<=>这样的其他关系Cologne

到目前为止,我有CompetenceType一个 EntityType 字段:

class CompetenceType extends AbstractType
{
    /**
     * @param FormBuilderInterface $builder
     * @param array $options
     */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add(
                'locations',
                EntityType::class,
                [
                    'class' => Location::class,
                    'choice_label' => 'name',
                    'multiple' => true,
                    'expanded' => true,
                    'label' => "Locations",
                ]
            );
    }
}

如何以Bob无法修改Munich关系但可以修改Berlin关系的方式设置表单?

我试图通过回调禁用该Munich选项choice_attr,但这会导致始终删除Munich关系。

我也尝试使用query_builder仅获取Berlin实体,但就像上面的解决方案一样,这会导致总是删除Munich关系。

第三个想法是设置并适当地修改加法器和删除器by_referencefalse我无法使用此解决方案,因为我无权访问实体内的容器,因此无法检查是否Bob有权操纵所有关系,而不仅仅是他自己的位置。

请注意:我想要一个不涉及控制器的解决方案。我知道我可以简单地通过控制器重新添加Munich关系,但这只是一个肮脏的黑客。在我看来,处理这个问题应该是表单的唯一责任。

标签: formssymfony

解决方案


我想说,只是一种形式只能带你走这么远。然而, ...

以某种方式EntityType独自管理这个不那么容易的任务。让表格承载一切?EntityType旨在处理一组统一的事物。

我的方法是区别处理实体(或链接或其他):可以编辑的实体和不能编辑的实体。我会使用DataMapper将实体分成这两组,一组可以设置为禁用(或完全省略),另一组可以进行编辑和填充,无论您需要什么。DataMapper::mapFormsToData在相反的方向然而,我从来没有这样做过......

如果您显示禁用的实体,您可能可以依靠禁用的表单来拒绝对不应更改的实体的任何更改。

所以,总结一下:

  • DataMapperInterface在您的表单类型上实现
  • mapDataToForms您将不可编辑的实体过滤到要编辑的一个字段中
  • mapFormsToData您必须再次过滤掉不可/可编辑的实体,以便您可以确定要添加/删除/编辑哪些实体

希望这会有所帮助……或者至少提供一种方法。


推荐阅读