Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 94d9bfb

Browse filesBrowse files
committed
bug #20378 [Form] Fixed show float values as choice value in ChoiceType (yceruto)
This PR was merged into the 2.7 branch. Discussion ---------- [Form] Fixed show float values as choice value in ChoiceType | Q | A | ------------- | --- | Branch? | 2.7 | Bug fix? | yes | New feature? | no | BC breaks? | no | Deprecations? | no | Tests pass? | yes | Fixed tickets | #13817 | License | MIT | Doc PR | - There is a closed [issue][1] related to this before Symfony 2.7 (when choice value still was the key from the `array`). This issue already happened in 2.7+ but now inside Symfony core. Information ----------- [This method][3] checks whether the given choices can be cast to strings without generating duplicates (3ab8189 in #16705): ```php private function castableToString(array $choices, array &$cache = array()) { foreach ($choices as $choice) { if (is_array($choice)) { if (!$this->castableToString($choice, $cache)) { return false; } continue; } elseif (!is_scalar($choice)) { return false; } elseif (isset($cache[$choice])) { // <---- red breakpoint return false; } $cache[$choice] = true; // <---- red breakpoint } return true; } ``` So it should to keep [scalar values (integer, float, string or boolean)][2] as choice values always (unless have duplicates values). The Problem ----------- But in this situation it doesn't happen: ```php $form = $this->createFormBuilder() ->add('foo', ChoiceType::class, [ 'choices' => [ 'Min' => 0.5, 'Mid' => 1.0, 'Max' => 1.5, ] ]) ->getForm(); ``` **Output:** ```html <select id="form_foo" name="form[foo]"> <option value="0">Min</option> <option value="1">Mid</option> <option value="2">Max</option> </select> ``` [**Why?**][5] If the key of the array is a float number, it's interpreted as integer automatically: ```php // ... $cache[$choice] = true; // when $choice = 0.5: $cache = [0 => true] // when $choice = 1.0: $cache = [0 => true, 1 => true] ``` Then, when `$choice = 1.5` [this sentence][4] `isset($cache[1.5])` returns `true` because really checks `isset($cache[1])` and this key already exists, so `castableToString()` returns `false` (detected as duplicate) and the choices values are generated incrementing integers as values. The PR's Effect ------------- **Before:** ```html <select id="form_foo" name="form[foo]"> <option value="0">Min</option> <option value="1">Mid</option> <option value="2">Max</option> </select> ``` **After:** ```html <select id="form_foo" name="form[foo]"> <option value="0.5">Min</option> <option value="1">Mid</option> <option value="1.5">Max</option> </select> ``` [1]: #13817 [2]: http://php.net/manual/en/function.is-scalar.php [3]: https://github.com/symfony/symfony/blob/2.7/src/Symfony/Component/Form/ChoiceList/ArrayChoiceList.php#L228 [4]: https://github.com/symfony/symfony/blob/2.7/src/Symfony/Component/Form/ChoiceList/ArrayChoiceList.php#L239 [5]: https://github.com/symfony/symfony/blob/2.7/src/Symfony/Component/Form/ChoiceList/ArrayChoiceList.php#L243 Commits ------- 3564228 [Form] Fix show float values as choices values in ChoiceType
2 parents f37ac13 + 3564228 commit 94d9bfb
Copy full SHA for 94d9bfb

File tree

Expand file treeCollapse file tree

2 files changed

+16
-3
lines changed
Filter options
Expand file treeCollapse file tree

2 files changed

+16
-3
lines changed

‎src/Symfony/Component/Form/ChoiceList/ArrayChoiceList.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/Form/ChoiceList/ArrayChoiceList.php
+5-1Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -236,7 +236,11 @@ private function castableToString(array $choices, array &$cache = array())
236236
continue;
237237
} elseif (!is_scalar($choice)) {
238238
return false;
239-
} elseif (isset($cache[$choice])) {
239+
}
240+
241+
$choice = false === $choice ? '0' : (string) $choice;
242+
243+
if (isset($cache[$choice])) {
240244
return false;
241245
}
242246

‎src/Symfony/Component/Form/Tests/ChoiceList/ArrayChoiceListTest.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/Form/Tests/ChoiceList/ArrayChoiceListTest.php
+11-2Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,12 +34,12 @@ protected function createChoiceList()
3434

3535
protected function getChoices()
3636
{
37-
return array(0, 1, '1', 'a', false, true, $this->object, null);
37+
return array(0, 1, 1.5, '1', 'a', false, true, $this->object, null);
3838
}
3939

4040
protected function getValues()
4141
{
42-
return array('0', '1', '2', '3', '4', '5', '6', '7');
42+
return array('0', '1', '2', '3', '4', '5', '6', '7', '8');
4343
}
4444

4545
/**
@@ -162,4 +162,13 @@ public function testGetChoicesForValuesWithContainingEmptyStringAndBooleans()
162162
$this->assertSame(array(0 => true), $choiceList->getChoicesForValues(array('1')));
163163
$this->assertSame(array(0 => false), $choiceList->getChoicesForValues(array('0')));
164164
}
165+
166+
public function testGetChoicesForValuesWithContainingEmptyStringAndFloats()
167+
{
168+
$choiceList = new ArrayChoiceList(array('Empty String' => '', '1/3' => 0.3, '1/2' => 0.5));
169+
170+
$this->assertSame(array(0 => ''), $choiceList->getChoicesForValues(array('')));
171+
$this->assertSame(array(0 => 0.3), $choiceList->getChoicesForValues(array('0.3')));
172+
$this->assertSame(array(0 => 0.5), $choiceList->getChoicesForValues(array('0.5')));
173+
}
165174
}

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.