前回のエントリで、モデルを拡張して読み出し時と保存時に正負反転させる方法を紹介しましたが、カラム名と実際の動作が逆になってしまって紛らわしいので、widgetとvalidatorで反転させることにしました。Symfony 1.4+Doctrineです。
既存のsfWidgetFormInputCheckboxとsfValidatorBooleanを継承して実装します。
lib/widget/sfWidgetFormInputCheckboxInverse.class.php
<?php class sfWidgetFormInputCheckboxInverse extends sfWidgetFormInputCheckbox { public function render($name, $value = null, $attributes = array(), $errors = array()) { if (!(null !== $value && $value !== false)) { $attributes['checked'] = 'checked'; } if (!isset($attributes['value']) && null !== $this->getOption('value_attribute_value')) { $attributes['value'] = $this->getOption('value_attribute_value'); } return parent::render($name, null, $attributes, $errors); } }
lib/validator/sfValidatorBooleanInverse.class.php
<?php class sfValidatorBooleanInverse extends sfValidatorBoolean { protected function configure($options = array(), $messages = array()) { parent::configure($options, $messages); $this->setOption('empty_value', true); } protected function doClean($value) { if (in_array($value, $this->getOption('true_values'))) { return false; } if (in_array($value, $this->getOption('false_values'))) { return true; } throw new sfValidatorError($this, 'invalid', array('value' => $value)); } }
ほぼ、逆にしたメソッドでオーバーライドしただけです。チェックボックスにチェックを入れなかった場合の挙動がデフォルトではfalseなので、trueに変更しています。
これをformクラスから
$this->widgetSchema['show_flag'] = new sfWidgetFormInputCheckboxInverse(); $this->validatorSchema['show_flag'] = new sfValidatorBooleanInverse();
のように定義してやればいいだけです。
例によってカラムのタイプがbooleanになっていることを確認してください。なっていないと0でも1でもtrueと判断されてしまうので。
$this->hasColumn('show_flag', 'boolean', null, array( 'type' => 'boolean', 'notnull' => true, 'default' => 0, ));