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

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();
本作品采用《CC 协议》,转载必须注明作者和本文链接
不乱于心,不困于情,不畏将来,不念过往,如此,安好!
《L03 构架 API 服务器》
你将学到如 RESTFul 设计风格、PostMan 的使用、OAuth 流程,JWT 概念及使用 和 API 开发相关的进阶知识。
《G01 Go 实战入门》
从零开始带你一步步开发一个 Go 博客项目,让你在最短的时间内学会使用 Go 进行编码。项目结构很大程度上参考了 Laravel。
讨论数量: 1
playmaker

分销出身吧?

8个月前 评论

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!