【问题标题】:Symfony Form EntityType doesn't select the current value on render by defaultSymfony Form EntityType 默认不选择渲染时的当前值
【发布时间】:2020-06-11 14:56:36
【问题描述】:

我偶然发现了一个奇怪的行为,我仍然不确定我的解决方案是否是最合适的,即使它现在有效。

我有 2 个实体:

class Recipe
{
    /** [...] */
    public $id;

    /** @ORM\Column(type="string", length=255) */
    public $name;

    /** @ORM\ManyToOne(targetEntity="App\Entity\Location") */
    public $location;
}

class Location
{
    /** [...] */
    public $id;

    /** @ORM\Column(type="string", length=255) */
    public $name;

    /** @ORM\OneToMany(targetEntity="App\Entity\Recipe", mappedBy="location") */
    protected $recipes;
}

这里没什么特别的。一个位置可以保存多个配方,一个配方最多可以在一个位置。

配方表单构建如下:

    public function buildForm(FormBuilderInterface $builder, array $options) {
        $builder
            ->add(
                'name',
                TextType::class,
                ['label' => 'Name',]
            )
            ->add(
                'location',
                EntityType::class,
                [
                    'label' => 'Location',
                    'class' => \App\Entity\Location::class,
                    'choice_value' => function ($location) {
                        // Why is this code necessary?
                        return is_object($location)
                            ? $location->getId()    // Object passed (when building choices)
                            : $location;            // int value passed (when checking for selection)
                    },
                    'choice_label' => 'name',
                ]
            )
        ;
    }

然后控制器创建表单等等。

    /**
     * @ParamConverter("entity", class="App:Recipe", isOptional="true")
     */
    public function edit(Request $request, object $entity = null) {
        $form = $this->createForm(\App\Form\Recipe::class, $entity ?? new Recipe());
        $form->handleRequest($request);
        if ($form->isSubmitted() && $form->isValid()) {
            // ...
        }
        // ...
    }

我的原始实现在EntityType 表单元素上没有上面的choice_value 回调,并且当我打开现有位置时从未选择过该选项。但除此之外,一切都按预期工作,选择一个值确实将其正确保存在数据库中,无需更多代码,但 Symfony 的魔力。

你能告诉我为什么这里需要choice_value吗?我错过了什么? 为什么作为参数传递的值有时是对象,有时是整数?

【问题讨论】:

    标签: php forms symfony


    【解决方案1】:

    通常没有必要。也许是因为实体之间的关系是单向的?

    有效的例子:

    在实体级别

    /**
     * @ORM\ManyToOne(targetEntity="App\Entity\Level", inversedBy="steps")
     */
    private $level;
    

    在实体步骤中

    /**
     * @ORM\OneToMany(targetEntity="App\Entity\Step", mappedBy="level")
     */
    private $steps;
    

    然后是 StepType :

    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('level', EntityType::class, [
                'label' => 'Related level',
                'class' => Level::class,
                'choice_label' => 'position'
            ])
        ;
    }
    

    【讨论】:

    • 嗯,这也是我的理解。关于单向链接,我可能过度简化了我的代码,因为我确实拥有它。我已经相应地编辑了我的帖子。
    【解决方案2】:

    不知道是不是问题的原因,但是对于EntityType字段,不需要手动设置choice_value

    来自Symfony docs

    在 EntityType 中,默认情况下会覆盖它以使用 id。当使用 id 时,Doctrine 只查询实际提交的 id 的对象。

    【讨论】:

      【解决方案3】:

      哦...找到了。实际上,我有一个旧的DataTransformer 与该字段相关联,并且它与值混淆。反正我不再需要它,所以只需将其移除就可以神奇地修复错误。

      无论如何,感谢您的帮助,它确实证实了某些事情是不对的,并迫使我深入挖掘。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-04-22
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多