Issues

ZF-3953: Zend_View_Helper_FormSelect incorrectly handles options with value 0

Description

The following code fails to properly select the option 'No' when the select box is rendered:

$form->addElement('select', 'like_candy', array(
    'label'    => 'Do you like candy?',
    'multiOptions' => array(
        array('key' => '1', 'value' => 'Yes'),
        array('key' => '0', 'value' => 'No'),
    ),
));
$form->like_candy->setValue('0');

This code fails for two reasons. First, in PHP it is not possible to use a string '0' for an array key. PHP will always automatically convert any numeric string to an integer when it is used as an array key, so the string '0' becomes the integer 0. Second, the fix for [ZF-1930] added a new condition that uses strict comparison between the option key and the element value whenever the option key is strictly equal to the integer 0. Because it is not possible to use the string '0' as an option key, there is no way to select the 'No' option using the string '0'.

This is a problem if the element {{$form->like_candy}} is being populated with a value queried from a database. Even if the value is stored in the database as an integer, it will always be stored as a string in a Zend_Db_Row object. Therefore, any time a select element could have the value 0 it is necessary to manually cast the element's value to an integer before calling {{$form->element->setValue()}}.

The following case also fails:

$form->addElement('select', 'like_candy', array(
    'label'    => 'Do you like candy?',
    'multiOptions' => array(
        array('key' => '1', 'value' => 'Yes'),
        array('key' => '0', 'value' => 'No'),
        array('key' => 'somewhat', 'value' => 'Somewhat'),
    ),
));
$form->like_candy->setValue(0);

This code will select both the 'No' option and the 'Somewhat' option. Because the option 'Somewhat' does not have a key of 0, Zend_View_Helper_FormSelect does not use strict comparison against the element values, and so the loose comparison of the string 'somewhat' and the integer 0 is a match. For any select element, setting the element value to 0 will cause every option with a non-numeric string key to be selected.

Both of these issues can be fixed by casting both the element values and the option keys to strings, like so:

Zend/View/Helper/FormSelect.php
@@ -71,1 +71,1 @@
-         $value = (array) $value;
+         $value = array_map('strval', (array) $value);
@@ -159,1 +159,1 @@
-         if (in_array($value, $selected, 0 === $value)) {
+         if (in_array((string) $value, $selected)) {

Comments

Scheduling for RC3.

Fixed in trunk and 1.6 release branch

Updating for the 1.6.0 release.