美文网首页
无限级分类之Laravel-nestedset扩展包的使用

无限级分类之Laravel-nestedset扩展包的使用

作者: 周星星的学习笔记 | 来源:发表于2020-12-18 23:50 被阅读0次

    Laravel-nestedset是Laravel框架中的一个无限级分类的扩展包,它的实现有别于传统的邻接表模型,采用的是一种新的分层数据模型叫嵌套集合模型,这种模型能够实现快速查询,运用在少修改、频查询的业务场景中能够提升较大的查询效率。下面我就带着大家一步一步来熟悉这个扩展。

    u=3352133920,2187839175&fm=26&gp=0.jpg

    一、首先安装扩展包

    1.进入到Laravel项目的根目录中,用composer安装kalnoy/nestedset。

    composer require kalnoy/nestedset
    

    二、创建模型以及对应的分类表

    1.创建好数据迁移文件。

    php artisan make:migration create_category_table
    

    2.进入database/migrations目录下,打开生成的迁移文件,并添加需要的字段。

    <?php
    
    use Illuminate\Database\Migrations\Migration;
    use Illuminate\Database\Schema\Blueprint;
    use Illuminate\Support\Facades\Schema;
    //引入NestedSet类
    use Kalnoy\Nestedset\NestedSet;
    
    class CreateCategoryTable extends Migration
    {
        /**
         * Run the migrations.
         *
         * @return void
         */
        public function up()
        {
            Schema::create('category', function (Blueprint $table) {
                //主键ID
                $table->id();
                //新增分类的名称字段
                $table->string('name')->default('');
                //在此添加此方法,nestedset将会自动生成:_lft、_rgt、parent_id三个字段
                NestedSet::columns($table);
                //根据实际场景需要决定需不需要软删除
                $table->softDeletes();
                //添加创建时间、更新时间字段
                $table->timestamps();
            });
        }
    
        /**
         * Reverse the migrations.
         *
         * @return void
         */
        public function down()
        {
            Schema::dropIfExists('category');
        }
    }
    

    3.迁移文件调整好之后,我们就可以执行迁移操作,创建出分类表,执行之后如下所示。

    php artisan migrate
    
    image.png
    image.png

    4.创建模型文件

    php artisan make:model CategoryModel
    

    5.打开该模型文件,引入NodeTrait。

    <?php
    
    namespace App\Models;
    
    use Illuminate\Database\Eloquent\Factories\HasFactory;
    use Illuminate\Database\Eloquent\Model;
    //引入NodeTrait
    use Kalnoy\Nestedset\NodeTrait;
    
    class CategoryModel extends Model
    {
        //使用NodeTrait
        use HasFactory,NodeTrait;
    
        protected $table = 'category';
    
        protected $fillable = ['name'];
    
    }
    

    6.若想要替换字段_lft、_rgt包括parent_id的名称可以做如下操作


    image.png
    image.png

    三、创建用于测试的路由以及控制器

    1.新增路由

    //显示节点
    Route::get('node/show',[CategoryController::class,'showNodes']);
    //创建节点
    Route::get('node/create',[CategoryController::class,'createNode']);
    //移动节点
    Route::get('node/move',[CategoryController::class,'moveNode']);
    //删除节点
    Route::get('node/delete',[CategoryController::class,'deleteNode']);
    
    

    2.新增控制器

    php artisan make:controller CategoryController
    
    <?php
    
    namespace App\Http\Controllers;
    
    use Illuminate\Http\Request;
    use App\Models\CategoryModel;
    
    class CategoryController extends Controller
    {
        //显示节点
        public function showNodes()
        {
    
        }
    
        //创建节点
        public function createNode()
        {
    
        }
    
        //移动节点
        public function moveNode()
        {
    
        }
    
        //删除节点
        public function deleteNode()
        {
    
        }
    }
    
    

    三、创建或插入分类节点

    (1)创建节点并添加到树节点的末端

    1.通过模型的构造方法传参的形式创建单节点

    $model = new CategoryModel(['name' => '节点A']);
    $model->save();
    

    2.直接针对模型的属性赋值来创建单节点

    $model = new CategoryModel();
    $model->name = '节点B';
    $model->save();
    

    3.调用模型的create方法创建单节点或者多节点(可包含子节点)

    //创建一个单节点,默认创建的节点在根节点
    CategoryModel::create(['name' => '节点C']);
    //一次性创建多个节点
    CategoryModel::create([
                'name' => '节点D',
                //使用children来定义子节点
                'children' => [
                    [
                        'name' => '节点E',
                        'children' => [
                            ['name' => '节点F']
                        ]
                    ],
                    [
                        'name' => '节点G'
                    ]
                ]
            ]);
    

    4.创建之后数据库数据以及树节点显示如下


    image.png
    [
        {
            "id": 1,
            "name": "节点A",
            "_lft": 1,
            "_rgt": 2,
            "parent_id": null,
            "deleted_at": null,
            "created_at": "2020-12-18T03:12:43.000000Z",
            "updated_at": "2020-12-18T03:12:43.000000Z",
            "children": []
        },
        {
            "id": 2,
            "name": "节点B",
            "_lft": 3,
            "_rgt": 4,
            "parent_id": null,
            "deleted_at": null,
            "created_at": "2020-12-18T03:13:11.000000Z",
            "updated_at": "2020-12-18T03:13:11.000000Z",
            "children": []
        },
        {
            "id": 3,
            "name": "节点C",
            "_lft": 5,
            "_rgt": 6,
            "parent_id": null,
            "deleted_at": null,
            "created_at": "2020-12-18T03:14:22.000000Z",
            "updated_at": "2020-12-18T03:14:22.000000Z",
            "children": []
        },
        {
            "id": 4,
            "name": "节点D",
            "_lft": 7,
            "_rgt": 14,
            "parent_id": null,
            "deleted_at": null,
            "created_at": "2020-12-18T03:14:46.000000Z",
            "updated_at": "2020-12-18T03:14:46.000000Z",
            "children": [
                {
                    "id": 5,
                    "name": "节点E",
                    "_lft": 8,
                    "_rgt": 11,
                    "parent_id": 4,
                    "deleted_at": null,
                    "created_at": "2020-12-18T03:14:46.000000Z",
                    "updated_at": "2020-12-18T03:14:46.000000Z",
                    "children": [
                        {
                            "id": 6,
                            "name": "节点F",
                            "_lft": 9,
                            "_rgt": 10,
                            "parent_id": 5,
                            "deleted_at": null,
                            "created_at": "2020-12-18T03:14:46.000000Z",
                            "updated_at": "2020-12-18T03:14:46.000000Z",
                            "children": []
                        }
                    ]
                },
                {
                    "id": 7,
                    "name": "节点G",
                    "_lft": 12,
                    "_rgt": 13,
                    "parent_id": 4,
                    "deleted_at": null,
                    "created_at": "2020-12-18T03:14:46.000000Z",
                    "updated_at": "2020-12-18T03:14:46.000000Z",
                    "children": []
                }
            ]
        }
    ]
    

    (2)为指定的父节点添加子节点,并且添加在子节点列表的尾部(若子节点已经存在,则会将该子节点移动到父节点的子节点列表中)

    1.使用子节点的appendToNode方法

    //首先创建一个子节点
    $node = new CategoryModel(['name' => '节点H']);
    //然后找一个父节点(假如以节点E作为父节点,id是5)
    $parentNode = CategoryModel::find(5);
    //将子节点添加到父节点中
    $node->appendToNode($parentNode)->save();
    

    2.使用父节点的appendNode方法

    //首先创建一个子节点
    $node = new CategoryModel(['name' => '节点I']);
    //然后找一个父节点(假如以节点E作为父节点,id是5)
    $parentNode = CategoryModel::find(5);
    //使用父节点的appendNode方法添加子节点
    $parentNode->appendNode($node);
    

    3.使用父节点的children()关系

    //首先找一个父节点(假如以节点E作为父节点,id是5)
    $parentNode = CategoryModel::find(5);
    //使用父节点的children()方法添加子节点
    $parentNode->children()->create(['name' => '节点J']);
    

    4.使用子节点的parent()关系的

    //首先创建一个子节点
    $node = new CategoryModel(['name' => '节点K']);
    //然后找一个父节点(假如以节点E作为父节点,id是5)
    $parentNode = CategoryModel::find(5);
    //使用子节点的parent()关系
    $node->parent()->associate($parentNode)->save();
    

    5.使用子节点的parent_id属性设置将子节点添加到指定的父节点

    //首先创建一个子节点
    $node = new CategoryModel(['name' => '节点L']);
    //然后找一个父节点(假如以节点E作为父节点,id是5)
    $parentNode = CategoryModel::find(5);
    //设置子节点的parent_id为父节点
    $node->parent_id = $parentNode->id;
    //设置完成之后保存
    $node->save();
    

    6.使用模型的静态方法将子节点添加到父节点中

    //首先找一个父节点(假如以节点E作为父节点,id是5)
    $parentNode = CategoryModel::find(5);
    //调用模型的create静态方法
    CategoryModel::create(['name' => '节点M'],$parentNode);
    

    7.从1~6方法执行之后,最终的树结构图如下所示

    //执行上面的代码之后,我们来查看一下树节点
    //新增加的节点都依次被添加到了节点E的children列表的尾部
     {
            "id": 4,
            "name": "节点D",
            "_lft": 7,
            "_rgt": 28,
            "parent_id": null,
            "deleted_at": null,
            "created_at": "2020-12-18T03:14:46.000000Z",
            "updated_at": "2020-12-18T03:14:46.000000Z",
            "children": [
                {
                    "id": 5,
                    "name": "节点E",
                    "_lft": 8,
                    "_rgt": 25,
                    "parent_id": 4,
                    "deleted_at": null,
                    "created_at": "2020-12-18T03:14:46.000000Z",
                    "updated_at": "2020-12-18T03:14:46.000000Z",
                    "children": [
                        {
                            "id": 6,
                            "name": "节点F",
                            "_lft": 9,
                            "_rgt": 10,
                            "parent_id": 5,
                            "deleted_at": null,
                            "created_at": "2020-12-18T03:14:46.000000Z",
                            "updated_at": "2020-12-18T03:14:46.000000Z",
                            "children": []
                        },
                        {
                            "id": 9,
                            "name": "节点H",
                            "_lft": 11,
                            "_rgt": 12,
                            "parent_id": 5,
                            "deleted_at": null,
                            "created_at": "2020-12-18T05:27:21.000000Z",
                            "updated_at": "2020-12-18T05:27:21.000000Z",
                            "children": []
                        },
                        {
                            "id": 11,
                            "name": "节点I",
                            "_lft": 15,
                            "_rgt": 16,
                            "parent_id": 5,
                            "deleted_at": null,
                            "created_at": "2020-12-18T05:40:55.000000Z",
                            "updated_at": "2020-12-18T05:40:55.000000Z",
                            "children": []
                        },
                        {
                            "id": 12,
                            "name": "节点J",
                            "_lft": 17,
                            "_rgt": 18,
                            "parent_id": 5,
                            "deleted_at": null,
                            "created_at": "2020-12-18T05:45:48.000000Z",
                            "updated_at": "2020-12-18T05:45:48.000000Z",
                            "children": []
                        },
                        {
                            "id": 13,
                            "name": "节点K",
                            "_lft": 19,
                            "_rgt": 20,
                            "parent_id": 5,
                            "deleted_at": null,
                            "created_at": "2020-12-18T05:53:22.000000Z",
                            "updated_at": "2020-12-18T05:53:22.000000Z",
                            "children": []
                        },
                        {
                            "id": 14,
                            "name": "节点L",
                            "_lft": 21,
                            "_rgt": 22,
                            "parent_id": 5,
                            "deleted_at": null,
                            "created_at": "2020-12-18T05:57:52.000000Z",
                            "updated_at": "2020-12-18T05:57:52.000000Z",
                            "children": []
                        },
                        {
                            "id": 15,
                            "name": "节点M",
                            "_lft": 23,
                            "_rgt": 24,
                            "parent_id": 5,
                            "deleted_at": null,
                            "created_at": "2020-12-18T06:02:43.000000Z",
                            "updated_at": "2020-12-18T06:02:43.000000Z",
                            "children": []
                        }
                    ]
                },
                {
                    "id": 7,
                    "name": "节点G",
                    "_lft": 26,
                    "_rgt": 27,
                    "parent_id": 4,
                    "deleted_at": null,
                    "created_at": "2020-12-18T03:14:46.000000Z",
                    "updated_at": "2020-12-18T03:14:46.000000Z",
                    "children": []
                }
            ]
        }
    

    (3)为指定的父节点添加子节点,并且添加在子节点列表的头部(若子节点已经存在,则会将该子节点移动到父节点的子节点列表中)

    1.使用子节点的prependToNode方法

    //首先创建一个子节点
    $node = new CategoryModel(['name' => '节点N']);
    //然后找一个父节点(假如以节点E作为父节点,id是5)
    $parentNode = CategoryModel::find(5);
    //通过子节点的prependToNode方法
    $node->prependToNode($parentNode)->save();
    

    2.使用父节点的prependNode方法

    //首先创建一个子节点
    $node = new CategoryModel(['name' => '节点O']);
    //然后找一个父节点(假如以节点E作为父节点,id是5)
    $parentNode = CategoryModel::find(5);
    //通过父节点的prependNode方法
    $parentNode->prependNode($node);
    

    3.执行以上两个操作之后的数据结构如下

    {
            "id": 4,
            "name": "节点D",
            "_lft": 7,
            "_rgt": 10,
            "parent_id": null,
            "deleted_at": null,
            "created_at": "2020-12-18T03:14:46.000000Z",
            "updated_at": "2020-12-18T03:14:46.000000Z",
            "children": [
                {
                    "id": 7,
                    "name": "节点G",
                    "_lft": 8,
                    "_rgt": 9,
                    "parent_id": 4,
                    "deleted_at": null,
                    "created_at": "2020-12-18T03:14:46.000000Z",
                    "updated_at": "2020-12-18T03:14:46.000000Z",
                    "children": []
                },
                {
                    "id": 5,
                    "name": "节点E",
                    "_lft": 12,
                    "_rgt": 33,
                    "parent_id": 4,
                    "deleted_at": null,
                    "created_at": "2020-12-18T03:14:46.000000Z",
                    "updated_at": "2020-12-18T06:51:59.000000Z",
                    "children": [
                        {
                            "id": 18,
                            "name": "节点O",
                            "_lft": 13,
                            "_rgt": 14,
                            "parent_id": 5,
                            "deleted_at": null,
                            "created_at": "2020-12-18T07:01:04.000000Z",
                            "updated_at": "2020-12-18T07:01:04.000000Z",
                            "children": []
                        },
                        {
                            "id": 17,
                            "name": "节点N",
                            "_lft": 15,
                            "_rgt": 16,
                            "parent_id": 5,
                            "deleted_at": null,
                            "created_at": "2020-12-18T06:53:11.000000Z",
                            "updated_at": "2020-12-18T06:53:11.000000Z",
                            "children": []
                        },
                        {
                            "id": 6,
                            "name": "节点F",
                            "_lft": 17,
                            "_rgt": 18,
                            "parent_id": 5,
                            "deleted_at": null,
                            "created_at": "2020-12-18T03:14:46.000000Z",
                            "updated_at": "2020-12-18T03:14:46.000000Z",
                            "children": []
                        },
                        {
                            "id": 9,
                            "name": "节点H",
                            "_lft": 19,
                            "_rgt": 20,
                            "parent_id": 5,
                            "deleted_at": null,
                            "created_at": "2020-12-18T05:27:21.000000Z",
                            "updated_at": "2020-12-18T05:27:21.000000Z",
                            "children": []
                        },
                        {
                            "id": 11,
                            "name": "节点I",
                            "_lft": 23,
                            "_rgt": 24,
                            "parent_id": 5,
                            "deleted_at": null,
                            "created_at": "2020-12-18T05:40:55.000000Z",
                            "updated_at": "2020-12-18T05:40:55.000000Z",
                            "children": []
                        },
                        {
                            "id": 12,
                            "name": "节点J",
                            "_lft": 25,
                            "_rgt": 26,
                            "parent_id": 5,
                            "deleted_at": null,
                            "created_at": "2020-12-18T05:45:48.000000Z",
                            "updated_at": "2020-12-18T05:45:48.000000Z",
                            "children": []
                        },
                        {
                            "id": 13,
                            "name": "节点K",
                            "_lft": 27,
                            "_rgt": 28,
                            "parent_id": 5,
                            "deleted_at": null,
                            "created_at": "2020-12-18T05:53:22.000000Z",
                            "updated_at": "2020-12-18T05:53:22.000000Z",
                            "children": []
                        },
                        {
                            "id": 14,
                            "name": "节点L",
                            "_lft": 29,
                            "_rgt": 30,
                            "parent_id": 5,
                            "deleted_at": null,
                            "created_at": "2020-12-18T05:57:52.000000Z",
                            "updated_at": "2020-12-18T05:57:52.000000Z",
                            "children": []
                        },
                        {
                            "id": 15,
                            "name": "节点M",
                            "_lft": 31,
                            "_rgt": 32,
                            "parent_id": 5,
                            "deleted_at": null,
                            "created_at": "2020-12-18T06:02:43.000000Z",
                            "updated_at": "2020-12-18T06:02:43.000000Z",
                            "children": []
                        }
                    ]
                }
            ]
        }
    

    (4)新增节点并插入到指定节点的前面或后面

    1.新增节点插入到指定节点的前面

    /*************************显性 save****************************/
    # 首先创建一个子节点
    $node = new CategoryModel(['name' => '节点Q']);
    # 然后找一个指定的节点(假如指定节点B,id是2)
    $neighbor = CategoryModel::find(2);
    # 将该节点插入到节点B的前面
    $node->beforeNode($neighbor)->save();
    /*************************显性 save****************************/
    
    //或者
    
    /*************************隐性 save****************************/
    # 首先创建一个子节点
    $node = new CategoryModel(['name' => '节点Q']);
    # 然后找一个指定的节点(假如指定节点B,id是2)
    $neighbor = CategoryModel::find(2);
    # 将该节点插入到节点B的前面
    $node->insertBeforeNode($neighbor);
    /*************************隐性 save****************************/
    
    // 执行之后树结构如下
    [
        {
            "id": 1,
            "name": "节点A",
            "_lft": 1,
            "_rgt": 2,
            "parent_id": null,
            "deleted_at": null,
            "created_at": "2020-12-18T03:12:43.000000Z",
            "updated_at": "2020-12-18T03:12:43.000000Z",
            "children": []
        },
        {
            "id": 20,
            "name": "节点Q",
            "_lft": 3,
            "_rgt": 4,
            "parent_id": null,
            "deleted_at": null,
            "created_at": "2020-12-18T09:41:48.000000Z",
            "updated_at": "2020-12-18T09:41:48.000000Z",
            "children": []
        },
        {
            "id": 2,
            "name": "节点B",
            "_lft": 5,
            "_rgt": 6,
            "parent_id": null,
            "deleted_at": null,
            "created_at": "2020-12-18T03:13:11.000000Z",
            "updated_at": "2020-12-18T03:13:11.000000Z",
            "children": []
        },
        ...
    ]
    

    2.新增节点插入到指定节点的后面

    /*************************显性 save****************************/
    # 首先创建一个子节点
    $node = new CategoryModel(['name' => '节点S']);
    # 然后找一个指定的节点(假如指定节点B,id是2)
    $neighbor = CategoryModel::find(2);
    # 将该节点插入到节点B的后面
    $node->afterNode($neighbor)->save();
    /*************************显性 save****************************/
    
    //或者
    
    /*************************隐性 save****************************/
    # 首先创建一个子节点
    $node = new CategoryModel(['name' => '节点S']);
    # 然后找一个指定的节点(假如指定节点B,id是2)
    $neighbor = CategoryModel::find(2);
    # 将该节点插入到节点B的后面
    $node->insertAfterNode($neighbor);
    /*************************隐性 save****************************/
    
    //执行之后树结构如下
    [
        {
            "id": 1,
            "name": "节点A",
            "_lft": 1,
            "_rgt": 2,
            "parent_id": null,
            "deleted_at": null,
            "created_at": "2020-12-18T03:12:43.000000Z",
            "updated_at": "2020-12-18T03:12:43.000000Z",
            "children": []
        },
        {
            "id": 20,
            "name": "节点Q",
            "_lft": 3,
            "_rgt": 4,
            "parent_id": null,
            "deleted_at": null,
            "created_at": "2020-12-18T09:41:48.000000Z",
            "updated_at": "2020-12-18T09:41:48.000000Z",
            "children": []
        },
        {
            "id": 2,
            "name": "节点B",
            "_lft": 7,
            "_rgt": 8,
            "parent_id": null,
            "deleted_at": null,
            "created_at": "2020-12-18T03:13:11.000000Z",
            "updated_at": "2020-12-18T03:13:11.000000Z",
            "children": []
        },
        {
            "id": 22,
            "name": "节点S",
            "_lft": 9,
            "_rgt": 10,
            "parent_id": null,
            "deleted_at": null,
            "created_at": "2020-12-18T09:57:56.000000Z",
            "updated_at": "2020-12-18T09:57:56.000000Z",
            "children": []
        },
        {
            "id": 3,
            "name": "节点C",
            "_lft": 11,
            "_rgt": 12,
            "parent_id": null,
            "deleted_at": null,
            "created_at": "2020-12-18T03:14:22.000000Z",
            "updated_at": "2020-12-18T07:29:22.000000Z",
            "children": []
        },
       ...
    ]
    

    四、获取分类节点

    1.将集合数据树形展现

    //树形结构展现(默认情况下,节点未进行排序展示,也就是说未根据depth字段进行排序)
    $tree = CategoryModel::get()->toTree();
    //采用默认排序再转换成树形(默认排序是根据depth字段从小到大的顺序)
    $tree = CategoryModel::defaultOrder()->get()->toTree();
    //采用倒序排序再转换成树形(倒序排序是根据depth字段从大到小的顺序)
    $tree = CategoryModel::reversed()->get()->toTree();
    

    2.获取节点数据的同时附带每个节点的深度

    //展现节点的时候,使用withDepth()方法,输出的数据会带一个深度字段depth
    $result = CategoryModel::withDepth()->get();
    //按照深度值来筛选出节点
    $result = CategoryModel::withDepth()->having('depth', '=', 1)->get();
    
    image.png

    3.获取兄弟节点

    //获取某个节点的兄弟节点
    $result = $node->getSiblings();
    $result = $node->siblings()->get();
    
    // 获取相邻的下一个兄弟节点
    $result = $node->getNextSibling();
    // 获取后面的所有兄弟节点
    $result = $node->getNextSiblings();
    // 使用查询获得所有兄弟节点
    $result = $node->nextSiblings()->get();
    
    // 获取相邻的前一个兄弟节点
    $result = $node->getPrevSibling();
    // 获取前面的所有兄弟节点
    $result = $node->getPrevSiblings();
    // 使用查询获得所有兄弟节点
    $result = $node->prevSiblings()->get();
    

    4.获取祖先和后代节点

    // 获取该节点的所有祖先节点
    $node->ancestors;
    // 获取该节点的所有后代节点
    $node->descendants;
    
    //获取$id这个节点的所有祖先节点
    $result = CategoryModel::ancestorsOf($id);
    //获取$id这个节点的所有祖先节点包括本节点
    $result = CategoryModel::ancestorsAndSelf($id);
    //获取$id这个节点的所有子节点
    $result = CategoryModel::descendantsOf($id);
    //获取$id这个节点的所有子节点包括本节点
    $result = CategoryModel::descendantsAndSelf($id);
    

    5.查询数据的条件约束

    //仅获取根节点
    $result = CategoryModel::whereIsRoot();
    //获取特定$id的节点后面的所有节点(不仅是兄弟节点)。
    $result = CategoryModel::whereIsAfter($id);
    //获取特定$id的节点前面的所有节点(不仅是兄弟节点)。
    $result = CategoryModel::whereIsBefore($id);
    
    //查询祖先的条件约束
    $result = CategoryModel::whereAncestorOf($node)->get();
    $result = CategoryModel::whereAncestorOrSelf($id)->get();
    
    //查询后代的条件约束
    $result = CategoryModel::whereDescendantOf($node)->get();
    $result = CategoryModel::whereNotDescendantOf($node)->get();
    $result = CategoryModel::orWhereDescendantOf($node)->get();
    $result = CategoryModel::orWhereNotDescendantOf($node)->get();
    $result = CategoryModel::whereDescendantAndSelf($id)->get();
    //结果集合中包含目标node自身
    $result = Category::whereDescendantOrSelf($node)->get();
    

    五、移动分类节点

    1.向上移动节点

    //获取需要移动的节点
    $node = CategoryModel::find(1);
    //将该节点向上移动1个位置
    $node->up();
    //将该节点向上移动3个位置(如果节点向上移动的位置超过了范围,则移动无效)
    $node->up(3);
    

    2.向下移动节点

    //获取需要移动的节点
    $node = CategoryModel::find(1);
    //将该节点向下移动1个位置
    $node->down();
    //将该节点向下移动3个位置(如果节点向下移动的位置超过了范围,则移动无效)
    $node->down(3);
    

    3.将一个已存在的节点设置为根节点

    //将节点E设置为根节点
    $node = CategoryModel::find(5);
    // 隐性 save
    $node->saveAsRoot();
    // 或者
    // 显性 save
    $node->makeRoot()->save();
    

    4.将一个已经存在的节点移动到指定节点的前面或后面(该方法与前述插入的方法一致,区别在于如果节点不存在则会新创建节点再移动,而如果节点已经存在则直接移动)

    $node = CategoryModel::find(5);
    $neighbor = CategoryModel::find(3);
    //显性save
    //将ID是5的节点移动到ID是3的节点的后面
    $node->afterNode($neighbor)->save();
    //将ID是5的节点移动到ID是3的节点的前面
    $node->beforeNode($neighbor)->save();
    
    //或者
    
    // 隐性 save
    //将ID是5的节点移动到ID是3的节点的后面
    $node->insertAfterNode($neighbor);
    //将ID是5的节点移动到ID是3的节点的前面
    $node->insertBeforeNode($neighbor);
    

    5.将一个节点移动到某个节点的子节点列表中(可以是列表的头部,也可以是列表的尾部),该部分参考「三」-(2)以及「三」-(3)。

    六、删除分类节点

    1.使用模型的delete方法删除,节点的所有后代元素将一并删除

    //删除
    $node = CategoryModel::find(19);
    $node->delete();
    

    2.不可以使用以下的语句删除,否则会破会树结构

    //不可以这样删除,请谨慎操作,否则破坏树结构
    🚫 CategoryModel::where('id', '=', $id)->delete();
    

    3.模型也支持软删除,在模型里面添加SoftDeletes trait

    <?php
    
    namespace App\Models;
    
    use Illuminate\Database\Eloquent\Factories\HasFactory;
    use Illuminate\Database\Eloquent\Model;
    use Illuminate\Database\Eloquent\SoftDeletes;
    use Kalnoy\Nestedset\NodeTrait;
    
    class CategoryModel extends Model
    {
        use HasFactory,NodeTrait,SoftDeletes;
    
        protected $table = 'category';
    
        protected $fillable = ['name'];
    
    }
    

    4.软删除之后我们可以查看表数据


    image.png

    七、帮助方法

    1.检查节点是否为其他节点的子节点

    $bool = $node->isDescendantOf($parent);
    

    2.检查是否为根节点

    $bool = $node->isRoot();
    

    3.检查树节点是否被破环

    $bool = CategoryModel::isBroken();
    

    4.检查当前节点是否是另外一个节点的子节点

    $bool = $node−>isChildOf($otherNode);
    

    5.检查当前节点是否是另外一个节点的

    $bool = $node−>isAncestorOf($otherNode);
    

    6.检查当前节点是否是另外一个节点的兄弟节点

    $bool = $node−>isSiblingOf($otherNode);
    

    7.检查当前节点是否是叶子节点

    $bool = $node->isLeaf();
    

    八、备注

    1.本文是在https://segmentfault.com/a/1190000012986277这篇文章的基础上,自己实际敲了例子整理而来,部分知识点我认为可能用不到,就未整理,如需进一步详细了解,可以去观看原文,或者直接访问扩展作者的github:https://github.com/lazychaser/laravel-nestedset

    相关文章

      网友评论

          本文标题:无限级分类之Laravel-nestedset扩展包的使用

          本文链接:https://www.haomeiwen.com/subject/qgntnktx.html