【问题标题】:Symfony Forms comparison between objects used as choice values and underlying dataSymfony Forms 在用作选择值的对象和基础数据之间进行比较
【发布时间】:2026-02-06 06:20:17
【问题描述】:

我使用的是 Symfony 2.8,但问题并不特定于这个版本。
假设我有 MyThingsFormType 这个字段:

$builder->add(
    'things',
    ChoiceType::class,
    [
        'multiple' => true,
        'choices_as_values' => true,
        'choices' => [
            'Thing no.20' => new Thing(20),
            'Thing no.21' => new Thing(21),
            'Thing no.22' => new Thing(22),
        ],
    ]
);

'data_class' => MyThings::class

MyThings 类定义为:

class MyThings
   private Thing[] $myThings

当我创建表单时,我会传递一个带有一些预填充选项的对象,例如:

$form = $this->formFactory->create(
    new MyThingsFormType(), 
    new MyThings([new Thing(21)])
);

关键是,我希望选择 Thing no.21 预先填充在视图中,因为我传递给表单的底层 MyThings 对象确实在 $myThings 数组中具有该对象...我知道它不是相同的对象,而只是一个具有相同数据的对象,而且显然 Symfony 进行了严格的比较,因此它不认为该选择是预先选择的......

那么,自定义该行为的最快和最干净的方法是什么,所以我可以考虑预先选择具有相同数据的选项,即使它们不是相同的对象?

【问题讨论】:

    标签: php symfony symfony-forms


    【解决方案1】:

    我在this response to a GitHub issue找到了解决方案。

    choice_value 的好处是 Symfony 也将使用这个闭包来比较两个不同的对象实例是否相等。

    诀窍就是使用choice_value 选项来确定选择的值。比如:

    'choice_value' => function (Thing $thing) {
        return $thing->getNumber();
    },
    

    此方法将在用作选择的 Thing 对象和作为数据传递的对象上调用,因此即使它们是不同的实例,它们也会被视为相等...

    【讨论】: