sfWidgetFormInputCheckbox unchecked bug

Warning! This post is either deprecated or outdated.

Ever tried to create a Symfony form with a check box input field, which by default should be unchecked ? No ? Well read on because it’s not that easy :).

This would be the code to print a check box input field in a Symfony form:

class CheckboxForm extends BaseCheckboxForm {
 public function configure() {
 $this->widgetSchema['field'] = new sfWidgetFormInputCheckbox();
 }
}

When you use the form to create something then by default the check box should be unchecked. And when you use this form for editing, then the check box should be checked if the object you try to edit has already been checked in the past.

If you try this code, you’ll see that the check box will always be checked. Even if you display this form to create a new object. Strange no ?

The problem is due to a bug in the Symfony sfWidgetFormInputCheckbox class. Even worse, this bug has been reported the first time 10 months ago (trac #3917) and 1 month later (trac #3996) and it’s still not fixed ! (grrrrr)

Until Symfony bug fixes this issue, there are 2 work a rounds you can use.

1. Edit the sfWidgetFormInputCheckbox class and patch it:

actual

class sfWidgetFormInputCheckbox extends sfWidgetFormInput
{
 ...
 public function render($name, $value = null, $attributes = array(), $errors = array())
 {
 if (!is_null($value) && $value !== false)
 {
 $attributes['checked'] = 'checked';
 }
 ...
 }
}

patched

class sfWidgetFormInputCheckbox extends sfWidgetFormInput
{
 ...
 public function render($name, $value = null, $attributes = array(), $errors = array())
 {
 if (!is_null($value) && $value !== false && $value != 0)
 {
 $attributes['checked'] = 'checked';
 }
 ...
 }
}

I would not recommend this, because if like us, you have more than one Symfony environment, there is a chance that you could forget to patch it. And worse if Symfony releases a new version without the bug fix you’ll have to remember to re patch the file.

2. Extend the sfWidgetFormInputCheckbox class and override the render method:

Edit: Put this class in the lib folder and call it myOwnWidgetFormInputCheckbox.class.php. After that run symfony cc.

/**
 * FIXME: This class can be removed if the sfWidgetFormInputCheckbox bug
 * has been resolved in symfony.
 */
class myOwnWidgetFormInputCheckbox extends sfWidgetFormInputCheckbox
{
 /**
 * Override render method due to symfony bug (http://trac.symfony-project.org/ticket/3917)
 */
 public function render($name, $value = null, $attributes = array(), $errors = array())
 {
 if (!is_null($value) && $value !== false && $value != 0)
 {
 $attributes['checked'] = 'checked';
 } 

 if (!isset($attributes['value']) && !is_null($this->getOption('value_attribute_value'))) {
 $attributes['value'] = $this->getOption('value_attribute_value');
 }

 return parent::render($name, null, $attributes, $errors);
 }
}

Your form class should then be changed to:

class CheckboxForm extends BaseCheckboxForm {
 public function configure() {
 $this->widgetSchema['field'] = new myOwnWidgetFormInputCheckbox();
 }
}

This was very easy to solve, but we lost a lot of time in finding the reason why this stupido check box was always checked. And why the hell is this bug still not solved in Symfony ?

In the mean time patch your symfony or create your own checkbox widget :).

By the way, if you found a typo, please fork and edit this post. Thank you so much! This post is licensed under a Creative Commons Attribution-ShareAlike 3.0 Unported License.

Comments

Fork me on GitHub