在Laravel中使用baum嵌套集合模型可以快速实现地区的添加和修改等无限极树状层级结构,比一般的递归效率要高出很多。
首先放上Baum的在GitHub的官网文档,不过是英文的。etrepat/baum。
这篇博客通过用Baum添加中国的省级、市级等关联的地区来讲一下如何简单操作Baum。
1.安装
composer require "baum/baum:~1.1"
2.配置
在config/app.php文件中
修改providers数组:
添加: Baum\Providers\BaumServiceProvider::class
修改aliases数组:
添加: 'Baum' => Baum\Providers\BaumServiceProvider::class
3.创建migration
安装到已存在的数据模型上:
php artisan baum:install MODEL
然后执行:
php artisan migrate
4.模型设置:
数据库设置:
+----+----------+-----------+------+------+-------+---------------------+---------------------+
| id | name | parent_id | lft | rgt | depth | created_at | updated_at |
+----+----------+-----------+------+------+-------+---------------------+---------------------+
| 1 | China | NULL | 1 | 10 | 0 | 2017-05-27 08:36:40 | 2017-05-27 08:36:40 |
| 2 | Zhejiang | 1 | 2 | 7 | 1 | 2017-05-27 08:36:40 | 2017-05-27 08:36:40 |
| 3 | Ningbo | 2 | 3 | 4 | 2 | 2017-05-27 08:36:40 | 2017-05-27 08:36:40 |
| 4 | Huzhou | 2 | 5 | 6 | 2 | 2017-05-27 08:36:40 | 2017-05-27 08:36:40 |
| 5 | Jiangsu | 1 | 8 | 9 | 1 | 2017-05-27 08:36:40 | 2017-05-27 08:36:40 |
+----+----------+-----------+------+------+-------+---------------------+---------------------+
<?php
namespace App;
use Baum\Node;
class Area extends Node
{
protected $table = 'tb_area';
// 'parent_id' column name
protected $parentColumn = 'parent_id';
// 'lft' column name
protected $leftColumn = 'lft';
// 'rgt' column name
protected $rightColumn = 'rgt';
// 'depth' column name
protected $depthColumn = 'depth';
protected $fillable = ['name'];
}
5.简单操作
<?php
namespace App\Http\Controllers;
use App\Area;
class AreaController extends Controller
{
public function __construct(){}
//插入方法1
public function insertArea1() {
//创建根节点
$root = Area::create(['name' => 'China']);
// 创建子节点
$zhejiang = $root->children()->create(['name' => 'Zhejiang']);
//方法2
$jiangsu = Area::create(['name' => 'Jiangsu']);
$jiangsu->makeChildOf($root);
//子节点的子节点
$ningbo = Area::create(['name' => 'Ningbo']);
$ningbo->makeChildOf($zhejiang);
}
//批量插入
public function insertArea2() {
//批量构建
$areaTree = [
['name' => 'China',
'children' => [
['name' => 'Zhejiang',
'children' => [
['name' => 'Ningbo'],
['name' => 'Huzhou']
]],
['name' => 'Jiangsu']
]],
];
Area::buildTree($areaTree); // => true
}
//输出所有
public function selectArea1() {
$node = Area::where('name', '=', 'China')->first();
foreach($node->getDescendantsAndSelf() as $descendant) {
echo $descendant->name."<br>";
}
}
//输出所有2 (带格式)
public function selectArea2() {
$node = Area::where('name', '=', 'China')->first();
echo $node->name."<br>";
foreach($node->getImmediateDescendants() as $descendant) {
echo " ".$descendant->name."<br>";
foreach($descendant->getImmediateDescendants() as $descendant2) {
echo " ".$descendant2->name."<br>";
}
}
}
//删除其中一条,并重组
public function deleteArea() {
$node = Area::where('name', '=', 'Ningbo')->delete();
Area::rebuild(true);
}
//修改节点
public function moveNode() {
$areaTree = [
['name' => 'China',
'children' => [
['name' => 'Zhejiang',
'children' => [
['name' => 'Ningbo'],
['name' => 'Huzhou'],
['name' => 'Fujian'] //这里需要修改
]],
['name' => 'Jiangsu']
]],
];
Area::buildTree($areaTree);
$zhejiang = Area::where('name', '=', 'Zhejiang')->first();
$fujian = Area::where('name','=', 'Fujian')->first();
$fujian->moveToLeftOf($zhejiang); //修改节点
}
}