カテゴリーツリーの表示

管理画面のカテゴリー管理部分を作る。

まずは、カテゴリー一覧画面。
カテゴリーはディレクトリのように無制限に階層構造をもたせたいので、一覧はツリー表示がしっくりくる。

CAKEPHP1.2では、ツリービヘイビアがあるということなのだが、情報が乏しい。

そんななか、下記のサイトがとても参考になった。

CakePHP1.2でツリー構造(Tree Behavior)を使う | エムティシステム

ツリービヘイビアでは、事前に用意するテーブルにもいろいろと項目が必要になっている。
今回用意したテーブルは下記の通り。

MySQL:
  1. DROP TABLE IF EXISTS `categories`;
  2. CREATE TABLE `categories` (
  3.    `id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
  4.    `parent_id` INT UNSIGNED NOT NULL DEFAULT '0',
  5.    `lft` INT DEFAULT '0',
  6.    `rght` INT DEFAULT '0',
  7.    `name` VARCHAR(32),
  8.    `title` VARCHAR(255),
  9.    `image` VARCHAR(255),
  10.    `meta_description` VARCHAR(255),
  11.    `meta_keywords` VARCHAR(255),
  12.    `description` TEXT,
  13.    `created` DATETIME,
  14.    `modified` DATETIME,
  15.    PRIMARY KEY (`id`),
  16.    KEY `idx_categories_parent_id` (`parent_id`),
  17.    KEY `idx_categories_lft` (`lft`)
  18. ) ENGINE=MyISAM DEFAULT CHARSET=utf8;

このうち、idとparent_idとlftとrghtがあることがツリービヘイビアの前提になっているようだ。
このなかで分かりづらいのがlftとrght。たぶん下記のページのようなアルゴリズムなんだろう。
これって一般的なのかな?

階層構造の取扱い - BestPC

さて、ツリービヘイビアの使い方だが、モデル(今回はCategoryモデル)に下記の一文をいれるだけ。

PHP:
  1. var $actsAs = array('Tree');

これで準備はOK。

今回は、カテゴリーをツリー表示したいというだけのことなので、あとはこれといってツリービヘイビアの機能を使っていない。
なお、コントローラからfindでデータを取ってくるときには、並び順をlftで指定したほうがいいみたい。(少なくとも下記のヘルパーを使う時は必須)

PHP:
  1. $cTree = $this->Category->find('all', array('order' => 'lft ASC', 'recursive' => -1));

表示のほうは、冒頭の参考サイトで紹介されていたTreeヘルパーが役に立った。

Tree Helper 1 (Articles) | The Bakery, Everything CakePHP

上記サイトからダウンロードしたものを/app/views/helpersに保存するだけ。

コントローラでは、最初にTreeヘルパーを使う指定をして、モデルから上記のようにとってきたデータをそのままビューに持っていく。

コントローラ(categories_controller.php)

PHP:
  1. var $helpers = array('Tree');

PHP:
  1. $cTree = $this->Category->find('all', array('order' => 'lft ASC', 'recursive' => -1));
  2.     $this->set('cTree', $cTree);

ビューでは、Treeヘルパーのgenerateメソッドを使ってツリー表示をする。
その際、ツリーの各ノードの表示を凝るために、エレメントを使う。

ビュー(admin_index.ctp)

PHP:
  1. echo $tree->generate($cTree, array('element' => 'ap_admin_c_tree'));

エレメント(ap_admin_c_tree.ctp)

PHP:
  1. <?php echo '<span>' . $html->link($data['Category']['title'], '/admin/categories/view/' . $data['Category']['id']) . '&nbsp;(' . $data['Category']['name'] . ')' . '</span>&nbsp;&nbsp;&nbsp;&nbsp;' . $html->link('[編集]', '/admin/categories/edit/' . $data['Category']['id']) . '&nbsp;&nbsp;' . $html->link('[子カテゴリの追加]', '/admin/categories/add/' . $data['Category']['id']) . '&nbsp;&nbsp;' . $html->link('[削除]', '/admin/categories/delete/' . $data['Category']['id'], null, sprintf('%sおよび所属する記事を削除してもよろしいですか?', $data['Category']['title'])); ?>

こんな感じで、簡単にツリー表示ができた。
もっと凝れば、ツリー表示を使って並び順の変更なんかもできるのかもしれないが、とりあえずはこれでOK。

ツリーヘルパーによるカテゴリー一覧

ツリーヘルパーによるカテゴリー一覧

Tags: ,