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 のドキュメントを見ていたら、ちゃんと記載がありました。

Virtual fields - 2.x

次のようにすると、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.

関連記事