3
2

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-nestedsetでデータをネストで扱う方法

Last updated at Posted at 2021-08-31

#はじめに
ページのカテゴリなどで使うデータをlaravel-nestedsetでネストで扱う方法を記載します。

・Laravel-nestedset 公式URL
https://github.com/lazychaser/laravel-nestedset

##環境
・PHP 8.0.1
・Laravel 8.40.0

##1. laravel-nestedのインストール

php composer.phar require kalnoy/nestedset:5.0.3

##2. マイグレーションファイルにnestedをセットする。

class CreateCategoriesTable extends Migration
{
    /**
     * Run the migrations.
     */
    public function up(): void
    {
        Schema::create('categories', function (Blueprint $table): void {
            $table->increments('id');
            $table->string('name');

            // '_lft' / '_rgt' / 'parent_id' が追加される
            $table->nestedSet();
        });
    }

マイグレーションを実行する

php artisan migrate:fresh

テーブルを確認する。「_lft」, 「_rgt」 「parent_id」 が追加される。

mysql> show columns from categories;
+-----------+------------------+------+-----+---------+-------------------+
| Field     | Type             | Null | Key | Default | Extra             |
+-----------+------------------+------+-----+---------+-------------------+
| id        | int(10) unsigned | NO   | PRI | NULL    | auto_increment    |     
| name      | varchar(100)     | NO   |     | NULL    |                   |
| _lft      | int(10) unsigned | NO   | MUL | NULL    |                   |
| _rgt      | int(10) unsigned | NO   |     | NULL    |                   |
| parent_id | int(10) unsigned | YES  |     | NULL    |                   |
+-----------+------------------+------+-----+---------+-------------------+

##3. カテゴリの登録

Category::create([
    'name' => '大カテゴリ',
    'children' => [
        [
            'name' => '中カテゴリ',
            'children' => [
                [ 'name' => '小カテゴリ' ],
            ],
        ],
    ],
]);

createを実行しデータを確認すると、以下のようなデータで登録される。

+------+------+-----------+----+--------------+
| _lft | _rgt | parent_id | id | name         | 
+------+------+-----------+----+--------------+
|    1 |    6 |      NULL |  1 | 大カテゴリ     | 
|    2 |    5 |         1 |  2 | 中カテゴリ     | 
|    3 |    4 |         2 |  3 | 小カテゴリ     | 
+------+------+-----------+----+--------------+

以下のようにも登録が可能。

$parent = Category::create(['name' => '大カテゴリ']); 
$children = Category::create(['name' => '中カテゴリ']); 
$children->appendTo($parent)->save();

##4. データ取得について

大カテゴリーの子孫(descendants)をリスト型式で取得する。

$parent = Category::find(1); // 大カテゴリー(id=1)
$categories = $parent->descendants()->get(); // 中カテゴリー、小カテゴリーをリストで取得
dd($categories->toArray()); // 配列形式で表示

-- データ結果 --
array:3 [
  0 => array:5 [
    "id" => 2
    "name" => "中カテゴリ"
    "_lft" => 2
    "_rgt" => 5
    "parent_id" => 1
  ]
  1 => array:15 [
    "id" => 3
    "name" => "小カテゴリ"
    "_lft" => 3
    "_rgt" => 4
    "parent_id" => 2
  ]
]

カテゴリーの先祖(ancestors)をリストで取得する。

$small = Category::find(3); // 小カテゴリー(id=3)
$categories = $small->ancestors()->get(); // 大カテゴリー、中カテゴリーをリストで取得
dd($categories->toArray()); // 配列形式で表示

-- データ結果 --
array:2 [
  0 => array:5 [
    "id" => 1
    "name" => "大カテゴリ"
    "_lft" => 1
    "_rgt" => 6
    "parent_id" => null
  ]
  1 => array:5 [
    "id" => 2
    "name" => "中カテゴリ"
    "_lft" => 2
    "_rgt" => 5
    "parent_id" => 1
  ]
]

カテゴリーをツリー形式(ネスト)で取得する。

$tree = Category::get()->toTree(); // ツリー形式(ネスト)で取得
dd($tree->toArray()); // 配列形式で表示

-- データ結果 --
array:1 [
  0 => array:6 [
    "id" => 1
    "name" => "大カテゴリ"
    "_lft" => 1
    "_rgt" => 6
    "parent_id" => null
    "children" => array:1 [
      0 => array:6 [
        "id" => 2
        "name" => "中カテゴリ"
        "_lft" => 2
        "_rgt" => 5
        "parent_id" => 1
        "children" => array:1 [
          0 => array:6 [
            "id" => 3
            "name" => "小カテゴリ"
            "_lft" => 3
            "_rgt" => 4
            "parent_id" => 2
            "children" => []
          ]
        ]
      ]
    ]
  ]
]

親カテゴリ(一番上位のカテゴリ)をリスト形式で取得する。

// カテゴリを登録
$parent = Category::create(['name' => '大カテゴリ']);
$parent2 = Category::create(['name' => '大カテゴリ2']);
$children = Category::create(['name' => '中カテゴリ']); 
$children->appendTo($parent1)->save();

// 親カテゴリ(一番上位のカテゴリ)をリスト形式で取得する。
$categories = Category::first()->whereIsRoot()->get();
dd($categories->toArray()); // 配列形式で表示

-- データ結果 --
array:2 [
  0 => array:5 [
    "id" => 1
    "name" => "大カテゴリ"
    "_lft" => 1
    "_rgt" => 2
    "parent_id" => null
  ]
  1 => array:5 [
    "id" => 2
    "name" => "大カテゴリ2"
    "_lft" => 3
    "_rgt" => 8
    "parent_id" => null
  ]
]
3
2
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
3
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?