CakePHP 2.0でGROUP BY や、SUM,COUNT,MIN() および MAX() ,を使う場合にはバーチャルフィールド(virtual fields)を使うと便利。
次のようなSQLを発行するときCakePHPではgroupを追加するのだが、結果の配列中にエイリアス指定したカラムがモデルの子にならず、ちょっと使いづらい。

sql
select id,count(id) as cnt from Table group by id;
php
$result = $this->Model->find('all', array( 'fields'=> array('id', 'count(id) as cnt'), 'conditions' => array('id >=',100), 'group' => array('id'), ));
php
Array ( [0] => Array ( [Model] => Array ( [id] => 1 ) [0] => Array ( [cnt] => 1 // ココに追加されてしまう。[0]は使いづらい。 ) ) [1] => Array ( [Model] => Array ( [id] => 2 ) [0] => Array ( [cnt] => 1 ) ) [2] => Array ( [Model] => Array ( [id] => 3 ) [0] => Array ( [cnt] => 1 ) )

何かないのとCakePHP のドキュメントを見ていたら、ちゃんと記載がありました。

Virtual fields

次のようにすると、Modelの要素として、cntが追加される。
・モデルにバーチャルフィールドを追加
・SQLのエイリアスの命名を Model__エイリアス にする。


(Modelのクラスにバーチャルフィールドを追加する方法もあるが、ここでは動的に追加している。)

php
$this->Model->virtualFields['cnt'] = 0; // バーチャルフィールドを追加 $result = $this->Model->find('all', array( 'fields'=> array('Model.id', 'count(Kwd.id) as Model__cnt'), // Model__エイリアスにする 'conditions' => array('Kwd.id < ' => 100 ), 'group' => array('Model.id'), )); ));
php
Array ( [0] => Array ( [Model] => Array ( [id] => 1 [cnt] => 1 //Modelの子に入った。 ) ) [1] => Array ( [Model] => Array ( [id] => 2 [cnt] => 1 ) ) [2] => Array ( [Model] => Array ( [id] => 3 [cnt] => 1 ) )

Virtual fieldsは、CakePHP 1.3でも使える模様。
Virtual fields are a new feature in the Model for CakePHP 1.3.