バグ解消法、お役立ち情報など

【CakePHP2】1つのテーブル内で階層構造を実現する方法

logo

はじめに

CakePHP2では、1つのテーブル内で階層構造のデータを扱うことができます。

この記事では、どのように階層構造を実現しているかを記載します。

階層構造とは?

階層構造とは、例えば以下のようなデータです。

  • 趣味(1階層目)
    • アウトドア系(2階層目)
      • ソロキャンプ(3階層目)
      • テニス(3階層目)
    • インドア系(2階層目)
      • 音楽鑑賞(3階層目)
      • 映画鑑賞(3階層目)

一番上の1階層目が「趣味」。

次の2階層目が「アウトドア系」および「インドア系」。

その次の3階層目が「ソロキャンプ」、「テニス」、「音楽鑑賞」、「映画鑑賞」です。

他には掲示板のスレッドなども階層構造になっていることが多いですね。

では、この階層構造はどのような仕組みで実現されているのでしょうか?

どうやって階層構造にしているか?

では、CakePHPではこの階層構造をどのように表現しているかをみていきます。

階層構造にしたいテーブルに、以下の3つのカラムを作成します。

  • 親レコードのID
  • 左端の座標
  • 右端の座標

CakePHPのドキュメントでは以下のように記載されています。

親 - デフォルトのフィールド名は「parent_id」です。親オブジェクトの id を格納するためのものです。

左端 - デフォルトのフィールド名は「lft」です。現在のオブジェク> トの 左端の座標を入力します。

右端 - デフォルトのフィールド名は「rght」です。現在のオブジェクトの 右端の座標を入力します。

Tree - 2.x

親、座標という概念については、偉大な先人たちが解説してくださっているのでぜひそちらをご覧ください。

階層構造 データベース - Google検索

ここではひとまず、「親と座標を定義すれば階層構造を作れる」と思っていただければ大丈夫です。

CakePHP2上で階層構造を扱うには?

では、実際に階層構造を実装していきます。

基本的にはドキュメントの通りで、特別難しいことはありません。

CakePHP2では、「Treeビヘイビア」を使用することで階層構造を扱えるようにします。

以下のような手順です。

  1. parent_id, lft, rghtカラムを含んだテーブルを作成。
  2. 1のテーブルにデータを挿入。(※あとで補足)
  3. モデル内に「$actAs」変数を宣言

これで以上です。

  1. のサンプルコードは以下の通りです。
CategoryModel
class Category extends AppModel { public $actsAs = array('Tree'); }

※ 2.のデータについて補足

parent_idさえきちんと設定すれば、lft, rghtは任意の値で問題ありません。

親IDが同一の場合は、テーブルの主キー(Primary Key)順に並べられます。

つまり、座標は気にせずに親IDだけ指定すれば良い、ということです。

ここがCakePHPの便利なポイントです。

通常は座標を1レコードずつ指定しないと想定通りの階層になりません。

lft, rgjtをどう調整するか?

CakePHP2上では、面倒なlft, rghtの調整は必要ありません。

ではどう調整するか?

下記の一行を記載するだけです。

$this->Category->recover();

はい。たったこれだけです。

処理の中で上記のメソッドを実行するだけで、座標が自動的に振り直されます。

これを初めて知った時は感動しましたね。

終わりに

以上、CakePHP2で階層構造を実現する方法でした。

CakePHP2はもう表舞台からは姿を消してしまいましたが、意外とまだ採用している現場も多いですよね。

これからも有益な情報などを得る機会があれば発信していきます。

ここまで読んでいただきありがとうございました!

バグ解消法、お役立ち情報など