Symfony - ChoiceType浮点值

时间:2016-10-31 10:18:00

标签: forms symfony

我在Symfony 3.1.6上运行,而且表单渲染让我感到奇怪。

这是我的表格:

    $form = $this->createFormBuilder()
        ->add('foo', ChoiceType::class, [
            'choices'     => [
                '00 h 30' => 0.5,
                '01 h 00' => 1.0,
            ],
        ])
        ->add('bar', ChoiceType::class, [
            'choices'     => [
                '00 h 30' => 0.5,
                '01 h 00' => 1.0,
                '01 h 30' => 1.5,
            ],
        ])
        ->add('baz', ChoiceType::class, [
            'choices'     => [
                '00 h 30' => 0.5,
                '01 h 00' => 1.0,
                '02 h 00' => 2.0,
            ],
        ])
        ->getForm();

基本渲染:

{{ form_start(form) }}
    {{ form_widget(form.foo) }}
    {{ form_widget(form.bar) }}
    {{ form_widget(form.baz) }}
{{ form_end(form) }}

我明白了:

<form>
    <select id="form_foo" name="form[foo]">
        <option value="0.5">00 h 30</option>
        <option value="1">01 h 00</option>
    </select>
    <select id="form_bar" name="form[bar]">
        <option value="0">00 h 30</option>
        <option value="1">01 h 00</option>
        <option value="2">01 h 30</option>
    </select>
    <select id="form_baz" name="form[baz]">
        <option value="0.5">00 h 30</option>
        <option value="1">01 h 00</option>
        <option value="2">02 h 00</option>
    </select>
</form>

为什么我的bar渲染没有显示好的值?事实上,每次我使用一个值&gt; 1并且没有舍入到int值,值只是int增量。

2 个答案:

答案 0 :(得分:1)

我很惊讶它产生了:

<option value="0">00 h 30</option>

然后

<option value="0.5">00 h 30</option>

用于相同的选项键和值(maybe because of this?)。

负责生成选择列表的类是Symfony/Component/Form/ChoiceList/ArrayChoiceList所以我在那里解决我的怀疑。

但是,我不知道导致此问题的原因我建议您查看ChoiceType字段的choice_value option,因为这决定了每个选项如何转换为值,如果是未指定它仅使用递增的idicies。所以也许尝试使用这个选项,只需将float转换为字符串。

请参阅:ArrayChoiceList.php#L83

答案 1 :(得分:1)

这是因为array的密钥必须只是integerstringPHP Manual)。如果提供了浮动键,则PHP会自动将其转换为整数here。让我们看一个例子:

$cache[$choice] = true;

// when $choice = 0.5: $cache = [0 => true]
// when $choice = 1.0: $cache = [0 => true, 1 => true]

然后,当$choice = 1.5 this lineisset($cache[1.5]))返回true因为真的检查isset($cache[1])并且此密钥已经存在,那么castableToString()会返回false(检测为重复)并生成选项值,将整数递增为值。

我认为这是一个错误。

目前,请使用choice_value选项修复该问题:

'choice_value' => function ($value) {
    return $value;
}

我在Github上留下了对这个老问题的评论:https://github.com/symfony/symfony/issues/13817#issuecomment-257297132

已在https://github.com/symfony/symfony/pull/20378

中修复