symfony 1.4にて。データベースの定義は「表示」フラグなのに、フォームでは「非表示」時にチェックを入れさせたい場合などがありまして。
データベースのカラム自体の意味を変えるのは、逆にフォームの意味が今後変わったときにどうするんだという話なので、今回はモデルでの入出力時点で値を変更する方法を試してみました。
actAsで各モデルの好きなカラムを反転できる拡張にしてみました。
lib/InvertBoolean.class.php
<?php class InvertBoolean extends Doctrine_Template { protected $_options = array( 'columns' => array() ); public function setTableDefinition() { $this->addListener(new InvertBooleanListener($this->_options)); } public function setUp() { } }
lib/model/invert_boolean/InvertBooleanListener.class.php
<?php class InvertBooleanListener extends Doctrine_Record_Listener { protected $_options; public function __construct(array $options) { $this->_options = $options; } public function postHydrate(Doctrine_Event $event) { $obj = $event->data; foreach ($this->_options['columns'] as $column) { $obj->$column = !($obj->$column); } $event->set('data', $obj); } public function preSave(Doctrine_Event $event) { foreach ($this->_options['columns'] as $column) { $value = !($event->getInvoker()->get($column)); $event->getInvoker()->set($column, $value); } } }
postHydrateでデータをデータベースから読み出してきてハイドレートした後に、preSaveで保存する前にそれぞれデータを反転しています。
カラムのタイプはあらかじめbooleanにしておく必要があります。schema.ymlからデータベース生成した場合は問題ないかと思います。そうでないなら、モデルのsetUpメソッドにでも
$this->hasColumn('show_flag', 'boolean', null, array( 'type' => 'boolean', 'notnull' => true, 'default' => 0, ));
など。
これを使用できるようにするために、同じくモデルのsetUpメソッドに
$this->actAs('InvertBoolean', array('columns'=>array('show_flag')));
とすればOKです。actAsのcolumnsオプションに複数カラム名設定すれば複数カラムを一括で指定できます。
これで、sfWidgetFormInputCheckboxを使ったチェックボックスにチェックを入れたときにデータベースに0が保存され、チェックを外すと1が保存されるカラムができあがりました。
問題点として、カラム名と反対の動きをすることになるので、うっかりする可能性が高まります。
なので、動作は確認しましたが、結局この案は使ってません。次のエントリーで紹介するカスタムウィジェットの方法を使っています。
[…] 前回のエントリで、モデルを拡張して読み出し時と保存時に正負反転させる方法を紹介しましたが、カラム名と実際の動作が逆になってしまって紛らわしいので、widgetとvalidatorで反転させることにしました。Symfony 1.4+Doctrineです。 […]