CakePHPで GROUP BY や SUM,COUNT とかを取る場合のバーチャルフィールド(virtual fields)利用
CakePHP 2.0でGROUP BYや、SUM,COUNT,MIN(),MAX()を使う場合、バーチャルフィールド(virtual fields)を使うと便利。
次のようなSQLを発行するときCakePHPではgroupを追加するのだが、結果の配列中にエイリアス指定したカラムがモデルの子にならず、ちょっと使いづらい。
select id,count(id) as cnt from Table group by id;
$result = $this->Model->find('all', array(
'fields'=> array('id', 'count(id) as cnt'),
'conditions' => array('id >=',100),
'group' => array('id'),
));
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 のドキュメントを見ていたら、ちゃんと記載がありました。
次のようにすると、Modelの要素として、cntが追加される。 ・モデルにバーチャルフィールドを追加 ・SQLのエイリアスの命名を Model__エイリアス にする。 (Modelのクラスにバーチャルフィールドを追加する方法もあるが、ここでは動的に追加している。)
$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'),
));
));
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.