ネストされたカテゴリーツリーをbaumで構築する方法
インストール
baumを利用してLaravel 4のEloquent ORMを拡張してツリータイプのデータ構造を生成します。
baumのページで使い方のマニュアルを確認することが出来ます。
composer.jsonに追記した上で
"require": { "laravel/framework": "4.2.*", "baum/baum": "~1.0" },
アップデートします。
composer update
app/config/app.php
のproviders配列に
‘Baum\BaumServiceProvider’,
を追記すればbaumが利用可能な状態になります。
カテゴリーテーブルの構築
baumの用途はカテゴリーツリーに限らず、ネスト化したコメントデータなどにも利用可能ですが、本記事ではカテゴリーテーブルを定義して、最終的にツリー形式のデータ構造を生成してみます。
以下のコマンドを実行すると、
php artisan baum:install category
app/models/Category.php
app/database/migrations/2014_11_21_094306_create_categories_table.php
ModelとMigrationファイルが自動生成されます。
今回は、Modelファイルは自動生成されたままの状態で、Migrationファイルを以下のように編集しました。
public function up() { Schema::create('categories', function(Blueprint $table) { $table->increments('id'); $table->integer('parent_id')->nullable()->index(); $table->integer('lft')->nullable()->index(); $table->integer('rgt')->nullable()->index(); $table->integer('depth')->nullable(); $table->string('name', 255); $table->string('slug', 255); $table->timestamps(); }); }
デフォルトの状態にslugフィールドを設定するように変更してみました。
- nameフィールドがカテゴリー名
- slugフィールドがカテゴリーURL
といったイメージです。
php artisan migrate
上のコマンドを実行すれば、データベースにcategoriesテーブルが定義されます。
管理系インタフェースの使い方
REPLの起動
テーブルを作成することが出来たので、カテゴリーデータを挿入してみます。Laravelに備わっているREPLタイプのコマンドラインからデータを追加するLaravelのコードを実行します。
php artisan tinker
ルートノードの作成
カテゴリーのルートノードを追加します。
$root = Category::create(['name' => 'Root', 'slug' => 'root']);
データベースにルートカテゴリーが挿入されていることが確認できます。
ノードの削除
$root->delete();
削除する必要がある場合は、上のコマンドで削除することが可能です。
子ノードの作成
ルートノードの子ノードを作成します。カテゴリー階層的には最初の階層になります。
$child1 = $root->children()->create(['name' => 'ホームページ', 'slug' => 'homepage']);
子ノードの子ノードを作成
サブカテゴリー(第二階層)を作成します。
$child2 = $child1->children()->create(['name' => 'ホームページビルダー', 'slug' => 'homepage-builder']);
取得系インタフェースの使い方
シンプルな例
REPLでカテゴリーデータを作成したので、カテゴリーデータを取得します。
$node = Category::where('slug', '=', 'homepage')->first(); foreach($node->getDescendants() as $descendant) { var_dump($descendant->name); }
上のコードでホームページカテゴリーのサブカテゴリーを取得出来ます。
ネスト化したデータ構造
toHierarchy()を利用して階層化されたデータ構造でカテゴリー情報を取得することが可能です。
$tree = Category::where('name', '=', 'Root')->first()->getDescendantsAndSelf()->toHierarchy();
$treeには階層化されたオブジェクトが返されます。以下のコードで配列に変換することが出来ます。
var_dump(json_decode(json_encode($tree), true));
データを確認すると、childrenキーでデータが階層化されていることが確認できます。
ネスト化されたツリー構造のデータを生成するライブラリとして、lazychaser/laravel-nestedset GitHubもあります。