默认情况下,Symfony Form EntityType不会选择渲染时的当前值

时间:2020-06-11 14:56:36

标签: php forms symfony

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

我有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()) {
            // ...
        }
        // ...
    }

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

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

3 个答案:

答案 0 :(得分:0)

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

有效的示例:

在实体级别

/**
 * @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'
        ])
    ;
}

答案 1 :(得分:0)

我不知道是不是问题的原因,但是对于public void Start(ICallback callback) { if (Callback != null) Stop(); Console.WriteLine("STARTING"); Callback = callback; cancellation = new CancellationTokenSource(); this.task = TaskLoopAsync(); Console.WriteLine("STARTED"); } public async void Stop() { if (Callback == null) { Console.WriteLine("ALREADY stopped"); return; } Console.WriteLine("STOPPING"); cancellation.Cancel(); try { await task; } catch (Exception e) { Console.WriteLine($"{e.Message}"); } finally { cancellation.Dispose(); cancellation = null; Callback = null; task = null; Console.WriteLine("STOPPED"); } } private async void TaskLoopAsync() { int i = 0; while (!cancellation.IsCancellationRequested) { await Task.Delay(1000); Console.WriteLine("Starting iteration... {0}", i); Callback.SendMessage($"Iteration {i} at {System.DateTime.Now}"); Console.WriteLine("...Ending iteration {0}", i++); } Console.WriteLine("CANCELLED"); } 字段,您不需要手动设置EntityType

来自Symfony docs

在EntityType中,默认情况下将其覆盖以使用id。使用ID时,Doctrine仅查询对象中实际提交的ID。

答案 2 :(得分:0)

哦...找到了。实际上,我有一个与该字段相关联的旧DataTransformer,它弄乱了值。我已经不再需要它了,所以只需将其神奇地删除即可解决该错误。

无论如何,感谢您的帮助,它确实确认了某些错误,并迫使我进行更深入的研究。