If you create a form select element with an options array with a 0 and string indexes, if the value is a string or 0, multiple options will be marked selected.
The form element:
$options = array('a'=> 'A', 0 => 'zero', 'b => 'B');
$form['foo'] = array(
'#type' => 'select',
'#title' => 'options...',
'#default_value' => 'a',
'#options' => $options,
);
Renders as:
<select name="edit[foo]" id="edit-foo" ><option value="a" selected="selected">A</option><option value="0" selected="selected">zero</option><option value="b">B</option></select>
PHP evaluates 'a' == 0 as true. 'a' is converted to a number, which will be zero, and they're considered equivalent. The solution is to convert the option key to a string before comparing it to the value.
The attached patch modifies the theme_select in form.inc to do this.
Comments
Comment #1
chx commentedFixed in http://drupal.org/node/39179
Comment #2
chx commented(sorry I misunderstood the problem, rereading makes me understand it)
quoting values is not a real solution to this. What about === ?
Comment #3
drewish commentedAren't most POSTed values strings? So you'd be forced to make all your indexes strings when you're building the options array. That prevents you from doing things like
$options = range(0, 5);...Is using quotes to cast it to a string really a problem?
Comment #4
jvandyk commentedHere's a patch with the === solution implemented. Both options with mixed keys and nested options work. Naturally one must put in the correct type in #default_value if you want a match (if your key is 0, '0' in #default_value will not match but 0 will).
Comment #5
drewish commentedjvandyk, that doesn't work either.
Put that control (after you fix the missing ') into a node form. Open up the form, set the value to an option with a numeric index and preview it. It'll preview correctly but you'll loose the selection on the form.
The reason is that the values POSTed are strings. As I said before, if you don't cast it to a string, you'd have to make sure that all your option indexes are either all numeric or, if you mix strings and numbers, non-zero.
Comment #6
drewish commentedwould casting using
(string)be better?Comment #7
chx commentedIf, you would comment it that it's a string cast, then I would lean to accepting it.
Comment #8
drewish commentedbased on the triple nesting of the ? : operator, i thought brevity was valued over readability :p
here's a patch using (string).
Comment #9
chx commentedMy friend, if you want to change it to more readable, rest assured it'll be welcomed warmly. Thanks for your hard work so far.
Comment #10
drewish commentedhere's a more-readable patch
Comment #11
moshe weitzman commentedquite a bit more readable. i can't test this now though.
Comment #12
drewish commentedHere's a re-roll that's current.
Comment #13
drewish commentedre-roll for head
Comment #14
drewish commentedit looks like someone else figured out this bug and added in a cast.
Comment #15
jamespvg commentedReopened as requested by drewish due to this related bug: http://drupal.org/node/45836.
Comment #16
drewish commentedHumm, chx just pointed out bug #45365 to me... It looks, to me, like it should have fixed it. That seems like a better place to continue this discussion so I'll mark this as fixed again.
Comment #17
(not verified) commented