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

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


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

<h2>CakePHPサブクエリのコード</h2>

<p>いきなりコードを載せます。</p>

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

<p>こんな感じになっています。</p>

<h2>サブクエリの記述について</h2>

<p><strong>サブクエリ</strong>は上部の10行程度で</p>

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

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

<p>この<strong>サブクエリ</strong>を使っている部分はfieldの部分で</p>

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

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

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

https://gist.github.com/revenue-hack/0eb93ff8c8ba91f48cc6edf715712cf2