CakePHPで2つのテーブルを連結させる

さて、極悪テーブル命名規則 T100,T200,T300 を magazines, publishers, users に変えることができたので、今度はテーブルの連結をしてみます。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<!-- views/magazines/index.ctp -->
<h2>雑誌一覧</h2>
<table>
    <tr>
        <td>id</td>
        <td>name</td>
        <td>publisher_id</td>
        <td>publisher_id</td>
    </tr>
<?php foreach($Magazines as $item) : ?>
    <tr>
        <td><?php echo $item['Magazine']['id'] ?></td>
        <td><?php echo $item['Magazine']['name'] ?></td>
        <td><?php echo $item['Magazine']['T200id'] ?></td>
        <td><?php echo $item['Magazine']['publisher_id'] ?></td>
    </tr>
<?php endforeach ; ?>
</table>

のように、publisher_id を表示させたって意味がないわけで、出版社名(Publisher.name)を表示させたい訳です。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<!-- views/magazines/index.ctp -->
<h2>雑誌一覧</h2>
<table>
    <tr>
        <td>id</td>
        <td>name</td>
        <td>publisher_id</td>
        <td>publisher_id</td>
    </tr>
<?php foreach($Magazines as $item) : ?>
    <tr>
        <td><?php echo $item['Magazine']['id'] ?></td>
        <td><?php echo $item['Magazine']['name'] ?></td>
        <td><?php echo $item['Magazine']['T200id'] ?></td>
        <td><?php echo $item['Magazine']['publisher_id'] ?></td>
        <td><?php echo $item['Publisher']['name'] ?></td> ★
    </tr>
<?php endforeach ; ?>
</table>

みたいに使えればいいですよね。使えるのかな?

という訳で、ひとつの雑誌(magazine)は、出版社(publisher)に属するということで、Magazine モデルを書き換えます。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<!-- models/magazine.php -->
<?php
class Magazine extends AppModel
{
    var $name = 'Magazine';
    var $useTable = 'T100';
    var $virtualFields = array(
        'publisher_id'=>'T200id' );
 
    var $belongsTo = array('Publisher' =>
        array(
            'className' => 'Publisher',
            'conditions' => '',
            'order' => 'Magazine.id ASC',
            'foreignKey' => 'T200id' ));
}
?>

この外部キーの書き方はいくつかあるのですが、$belongsTo と $hasMeny は双方向なのでどちらか決めで使えばいいんでしょう。

こうすると、先の index.ctp が動きます。生成される SQL を見ると、

1
2
3
4
5
6
7
8
9
10
11
12
SELECT
 `Magazine`.`id`,
 `Magazine`.`name`,
 `Magazine`.`T200id`,
 `Magazine`.`price`,
 (T200id) AS `Magazine__publisher_id`,
 `Publisher`.`id`,
 `Publisher`.`name`
FROM `T100` AS `Magazine`
 LEFT JOIN `T200` AS `Publisher` ON (`Magazine`.`T200id` = `Publisher`.`id`)
WHERE 1 = 1
 ORDER BY `Magazine`.`id` ASC

となっているので、left join が使われていますね。なるほど。

残念ながら $virtualFields で別名定義をしたカラム名は、$belongsTo では使えないようで、あの不思議な T200id というカラム名が出てきますが、まぁ、良しとしましょう。適当なヘルパー関数なりを作れば、このあたりの設定も楽になると思います。$virtualFields が連想配列なので、逆引きして value から key を取り出せばよいので。

カテゴリー: 雑談, CakePHP パーマリンク

CakePHPで2つのテーブルを連結させる への2件のフィードバック

  1. konica のコメント:

    お、把握。
    勉強になる(´・ω・)ス
    引き続きヲチ

    • masuda のコメント:

      ひとまず、テーブルの連結は最悪 Model::query を使えばよいことまで確認できました。最初はフレームワークの最小限のメソッドだけ使って、あとは徐々に置き換えかなあと。

コメントは停止中です。