Akelosで多対多(has_and_belongs_to_many)のテーブルを使う

引き続きAkelosのモデル周りの動作テスト。

Akelosで多対多のテーブルを使いたいとき、Railsと同じくhas_and_belongs_to_manyが使える。

使い方は簡単でたとえば以下のような感じでテーブル設計がされている場合

+-------+     +--------------+     +--------+
| users |     | groups_users |     | groups |
+-------+     +--------------+     +--------+
| id    |--+  | id           |  +--| id     |
| name  |  +--| user_id      |  |  | name   |
+-------+     | group_id     |--+  +--------+
              +--------------+

※usersテーブルとgroupsテーブルを関係性をgroups_usersテーブルで表す多対多のテーブル。

それぞれのモデルで以下のようにすれば使える。

app/models/user.php

<?php
class User extends ActiveRecord
{
  var $has_and_belongs_to_many = 'groups';
}
?>

app/models/group.php

<?php
class Group extends ActiveRecord
{
  var $has_and_belongs_to_many = 'users';
}
?>

あとはコントローラ側で

app/controllers/sample_controller.php

<?php
class SampleController extends ApplicationController
{
  function index()
  {
    Ak::import('User');
    $User = new User(1);
    $User->groups->load();
    print($User->toYaml());
    print($User->groups[0]->toYaml());
  }
}
?>

たったこれだけで使えてしまう。あっけなさすぎる。

もちろんコレはAkelos命名規則に沿ってテーブルを定義しているからだけど、そうじゃない場合でも「$has_and_belongs_to_many」の定義が若干変わる程度。

ちなみに命名規則は以下のような感じ。

  • XsとYsを多対多で使いたい場合は連結するテーブル名にXs_Ysテーブルを使う
  • Xs_Ysの名前はソートして早い順に名前をつける(hogesとfugasならfugas_hogesになる)
  • Xs_YsテーブルにはそれぞれのIDであるx_id,y_idをカラム名として用意

とりあえずこれだけ守れば上記のような感じで使える。

命名規則に従わない場合は以下のようにすればいい。

<?php
class User extends ActiveRecord
{
  // 連結テーブル名を変更する場合
  var $has_and_belongs_to_many = array('groups' => array('join_table' => 'membership'));
  // 連結テーブルでのforeignKeyを変更する場合
  var $has_and_belongs_to_many = array('groups' => array('foreignKey' => 'user'));
}
?>

AkHasAndBelongsToMany.phpのソース見た感じではもっと細かく定義できるみたいだけど、特に理由がない限り基本的に命名規則に従って設計した方が幸せになれそう。