cakePHP2でサブクエリを使う方法


会社ではgoとかjavaとかkotlinを書いています。
前職でphp書いてました。

このエントリーはcakePHPサブクエリの書き方についてです。フィールドにサブクエリを書こうとした時、あまりエントリーもなくcakeのドキュメントも不親切だったので、メモついでに書くことにしました。

CakePHPサブクエリのコード

いきなりコードを載せます。



// とあるmodelでの記述です。
// データソースを定義
$db = $this->getDataSource();
// ここからサブクエリの記述
$subQuery =  $db->buildStatement(
    array(
        'fields' => ['cate2.c_title'],
        'table' => 'publish_categories',
        'alias' => 'cate2',
        'conditions' => ['cate2.cate1_e=cate.cate1_e and cate2.cate2_e=cate.cate2_e and cate.site_id=cate2.site_id and cate2.level = 2'],
    ),$this->model名
);
Configure::load('site_zone_lists.php');
// 以下のクエリ内にサブクエリを使う
$data = $this->find('all', [
    'table' => 'publish_site_submissions',
    'fields' => [
        'model名.id',
        'model名.site_zone_id',
        'model名.navias_deal_item_id',
        'model名.start_date',
        'b.brand_name_jp',
        'b.brand_display_name',
        'sz.zone_name',
        'np.product_name',
        // サブクエリを設定しています
        '('.$subQuery.') as middle_title',
    ],
    'joins' => [
        [
            'table' => 'site_zones',
            'alias' => 'sz',
            'conditions' => ['sz.id = model名.site_zone_id']
        ],
        [
            'table' => 'brands',
            'alias' => 'b',
            'conditions' => ['model名.brand_id = b.id']
        ],
        [
            'table' => 'site_submission_category_relations',
            'alias' => 'scr',
            'conditions' => ['scr.site_submission_id = model名.id']
        ],
        [
            'table' => 'publish_categories',
            'alias' => 'cate',
            'conditions' => ['cate.id = scr.category_id']
        ],
        [
            'table' => 'navias_deal_products',
            'alias' => 'ndp',
            'conditions' => ['ndp.deal_item_id = model名.navias_deal_item_id']
        ],
        [
            'table' => 'navias_products',
            'alias' => 'np',
            'conditions' => ['np.product_id = ndp.product_id']
        ],
    ],
    'conditions' => [
        'b.id' => $brandIds,
        'ctool_display_flag' => 1,
        'model名.site_zone_id' => Hash::extract(Configure::read('site_zone_lists'), '{s}.zone_id')
    ],
    'group' => 'model名.id',
]);
foreach ($data as &$values) {
    $tmp = array();
    foreach ($values as $value) {
        $tmp = array_merge($tmp, $value);
    }
    $values = $tmp;
    $values['product_name_detail'] = preg_match('/.+_(.*)_.+/', $values['product_name'], $matches) ? $matches[1] : null;
}
return $data;

こんな感じになっています。

サブクエリの記述について

サブクエリは上部の10行程度で



// データソースを定義
$db = $this->getDataSource();
// ここからサブクエリの記述
$subQuery =  $db->buildStatement(
    array(
        'fields' => ['cate2.c_title'],
        'table' => 'publish_categories',
        'alias' => 'cate2',
        'conditions' => ['cate2.cate1_e=cate.cate1_e and cate2.cate2_e=cate.cate2_e and cate.site_id=cate2.site_id and cate2.level = 2'],
    ),
    // ここでmodl名を定義
    $this->model名
);

まずデータソースを定義したのち、サブクエリを書いていきます。書き方はfindの時とほぼ変わらず、最後にmodel名を指定しています。

このサブクエリを使っている部分はfieldの部分で



'fields' => [
    'model名.id',
    'model名.site_zone_id',
    'model名.navias_deal_item_id',
    'model名.start_date',
    'b.brand_name_jp',
    'b.brand_display_name',
    'sz.zone_name',
    'np.product_name',
    // サブクエリを設定しています
    '('.$subQuery.') as middle_title',
],

フィールドの最後のお部分で文字列連結して使っています。

これでフィールドがサブクエリ内で使えるようになりました。