2009年3月10日火曜日

CakePHP 1.2 で自己参照HABTMアソシエーション (Self-Referential HABTM Relationships) をページングする

2009年3月10日火曜日
Cakebaker (Daniel Hofstetter) が以前書いた記事の中に、"Pagination of data from a HABTM relationship" という素晴らしい記事があります。この記事は 、HABTMアソシエーションのデータを CakePHP 1.2 を使ってどのようにページングするのかについて書かれたものです。 Daniel に触発されて、Kyo は自己参照HABTMアソシエーション (Self-Referential HABTM Relationships) をページングする方法を紹介します。 この方法は CakePHP 1.2.1.8004 でテストしましたが、それより古いバージョンでは動作しないかもしれません。 まず、 User model を用意しましょう。ある User に対して Friends をページングします。テーブル定義は次のようになります。
create table users (
  id int(11) not null auto_increment,
  username varchar(32) not null,
  primary key (id)
);

create table users_friends (
  id int(11) not null auto_increment,
  user_id int(11) not null,
  friend_id int(11) not null,
  primary key (id)
);
作成したテーブルにテストデータをインサートしましょう。
insert into users (id, username) values (1, 'kevin');
insert into users (id, username) values (2, 'stephanie');
insert into users (id, username) values (3, 'michael');
insert into users (id, username) values (4, 'jennifer');

insert into users_friends (user_id, friend_id) values (1, 2);
insert into users_friends (user_id, friend_id) values (1, 3);

insert into users_friends (user_id, friend_id) values (2, 1);
insert into users_friends (user_id, friend_id) values (2, 4);

insert into users_friends (user_id, friend_id) values (3, 1);
insert into users_friends (user_id, friend_id) values (3, 4);

insert into users_friends (user_id, friend_id) values (4, 2);
insert into users_friends (user_id, friend_id) values (4, 3);
自己参照HABTMアソシエーションを User model で設定します。
class User extends AppModel {
  var $name = 'User';
  var $hasAndBelongsToMany = array(
    'Friend' => array(
      'className' => 'User',
      'joinTable' => 'users_friends',
      'foreignKey' => 'user_id',
      'associationForeignKey' => 'friend_id',
      'unique' => true,
    )
  );
}
ユーザ “kevin” の ID から、その友達をページングします。Nate のチュートリアル "Quick Tip - Doing Ad-hoc Joins in Model::find()" を参考に、コントローラを作成します。
// app/controllers/friends_controller.php
class FriendsController extends AppController {
  function index() {
    $this->paginate = array(
      'Friend' => array(
        'limit' => 2,
        'joins' => array(
          array(
            'table' => 'users_friends',
            'alias' => 'UsersFriend',
            'type' => 'inner',
            'conditions'=> array(
              'UsersFriend.friend_id = Friend.id',
            ),
          ),
          array(
            'table' => 'users',
            'alias' => 'User',
            'type' => 'inner',
            'conditions'=> array(
              'User.id = UsersFriend.user_id',
              'User.id' => 1
            )
          )
        )
      )
    );
    $data = $this->paginate('Friend');
    debug($data);
    exit;
  }
}
デバッグアウトプットは以下の通りです。
Array
(
[0] => Array
   (
       [Friend] => Array
           (
               [id] => 2
               [username] => stephanie
               [0] => Array
                   (
                       [id] => 1
                       [username] => kevin
                       [UsersFriend] => Array
                           (
                               [id] => 3
                               [user_id] => 2
                               [friend_id] => 1
                           )
                   )
               [1] => Array
                   (
                       [id] => 4
                       [username] => jennifer
                       [UsersFriend] => Array
                           (
                               [id] => 4
                               [user_id] => 2
                               [friend_id] => 4
                           )
                   )
           )
   )
[1] => Array
   (
       [Friend] => Array
           (
               [id] => 3
               [username] => michael
               [0] => Array
                   (
                       [id] => 1
                       [username] => kevin
                       [UsersFriend] => Array
                           (
                               [id] => 5
                               [user_id] => 3
                               [friend_id] => 1
                           )
                   )
               [1] => Array
                   (
                       [id] => 4
                       [username] => jennifer
                       [UsersFriend] => Array
                           (
                               [id] => 6
                               [user_id] => 3
                               [friend_id] => 4
                           )
                   )
           )
   )
)

0 コメント:

コメントを投稿

 
JamNite Japan ◄Design by Pocket, BlogBulk Blogger Templates