9
7

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Laravelで閉包テーブル(Closure Table) を簡単に実現してくれるライブラリ ClosureTable

Last updated at Posted at 2019-08-21

Laravelで閉包テーブル(Closure Table) を簡単に実現してくれるライブラリ ClosureTable

DBのツリー構造のテーブルにはいくつかありますが、その中に閉包テーブルというものがあります。
この記事にたどり着く人には説明不要だと思うので説明は省きます!!!!

各ツリー構造についてはこちらの記事がわかりやすい気がします!
https://qiita.com/hirashunshun/items/06adf4f42f03a9f3b63d

実際に閉包テーブルを自前で実現しようとすると、CRUDのクエリ投げるときに整合性とれてるのかこれ。。。って部分があり、孫だけ取得とかそのへんのクエリをゴリゴリ書くのは面倒な部分が多く、そこがデメリットな感じもします

本題

ゴリゴリクエリ書くのが面倒だなーというデメリットを解決してくれるのがこれ!
https://github.com/franzose/ClosureTable

テーブル構造のことなんて何も考えず脳死で閉包テーブルが作れます!
めちゃくちゃ良いライブラリだと思います

使い方 ~Migration編

ライブラリが提供しているコマンドでmigrationを作成

php artisan closuretable:make --entity=trees

すると、migration・Model・Interfaceとかが作られる

create  2019_08_19_105450_create_trees_table_migration
create  Tree
create  TreesInterface
create  TreesClosure
create  TreesClosureInterface
2019_08_19_105450_create_trees_table_migration
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class CreateTreesTableMigration extends Migration
{
    public function up()
    {
        Schema::create('trees', function (Blueprint $table) {
            $table->increments('id');
            $table->integer('parent_id')->unsigned()->nullable();
            $table->integer('position', false, true);
            $table->integer('real_depth', false, true);
            $table->softDeletes();

            $table->foreign('parent_id')
                ->references('id')
                ->on('trees')
                ->onDelete('set null');
        });

        Schema::create('trees_closure', function (Blueprint $table) {
            $table->increments('closure_id');

            $table->integer('ancestor', false, true);
            $table->integer('descendant', false, true);
            $table->integer('depth', false, true);

            $table->foreign('ancestor')
                ->references('id')
                ->on('trees')
                ->onDelete('cascade');

            $table->foreign('descendant')
                ->references('id')
                ->on('trees')
                ->onDelete('cascade');
        });
    }

    public function down()
    {
        Schema::table('trees_closure', function (Blueprint $table) {
            Schema::dropIfExists('trees_closure');
        });

        Schema::table('trees', function (Blueprint $table) {
            Schema::dropIfExists('trees');
        });
    }
}

最低限の構造を作ってくれます。必要であれば、カラムとか追加可能
基本的にはtrees側に追加すればよいかと

interface抜粋

Treeinterface

use Franzose\ClosureTable\Contracts\EntityInterface;

interface treesInterface extends EntityInterface
{
}

継承しているInterfaceがClosureTable独自のものになっている

モデル

Tree.php
use Franzose\ClosureTable\Models\Entity;

class trees extends Entity implements treesInterface
{
    /**
     * The table associated with the model.
     *
     * @var string
     */
    protected $table = 'trees';

    /**
     * ClosureTable model instance.
     *
     * @var treesClosure
     */
    protected $closure = 'App\treesClosure';
}

継承しているEntityがClosureTable独自のものになっている

この辺のclass名がloweerCaseなのは気持ち悪いので好みで変える…!

protected $closure = 'App\treesClosure';

使い方 ~ぷりょぐらむ編

一番上のモデルを作る時

$rootTree = new Tree();
$rootTree->save();

普通にモデル作るのと同じ

子供追加

// 親作る
$rootTree = new Tree();
$rootTree->save();

// 子供作る
$childTree = new Tree();
$rootTree->addChild($childTree);
$childTree->save();

// 子供2作る
$childTree2 = new Tree();
$rootTree->addChild($childTree2);
$childTree2->save();

これもいい感じにできる

削除

// 親作る
$rootTree = new Tree();
$rootTree->save();

// 子供作る
$childTree = new Tree();
$rootTree->addChild($childTree);
$childTree->save();

// 子供2作る
$childTree2 = new Tree();
$rootTree->addChild($childTree2);
$childTree2->save();

// 子供達だけ削除の場合
$rootTree->deleteSubtree();
// 自分を含む子供達を削除する場合
$rootTree->deleteSubtree(true);

取得


$rootTree = Tree::find(いつもの);

// これで子供達とれる(孫まで取れるわけではないので再帰処理とか別メソッドを使う必要がある
$children = $rootTree->getChildren();

こんなかんじ

書くのが辛くなったのでまとめ

使いやすい!

各メソッドはいい感じに抽象化されてて使いやすい!公式みて!!
https://github.com/franzose/ClosureTable#ancestors

使ってみて!!

9
7
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
9
7

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?