wbraganca / yii2-nested-set-behavior
该扩展允许您获取嵌套集合树的函数。
Requires
- yiisoft/yii2: *
This package is not auto-updated.
Last update: 2024-09-10 03:09:59 UTC
README
该扩展允许您获取嵌套集合树的函数。
安装
安装此扩展的首选方式是通过 composer。
运行
php composer.phar require wbraganca/yii2-nested-set-behavior "*"
或添加
"wbraganca/yii2-nested-set-behavior": "*"
到您的 composer.json
文件的 require 部分。
配置
首先,您需要按照以下方式配置模型
use wbraganca\behaviors\NestedSetBehavior; use wbraganca\behaviors\NestedSetQuery; class Category extends ActiveRecord { public function behaviors() { return [ [ 'class' => NestedSetBehavior::className(), // 'rootAttribute' => 'root', // 'levelAttribute' => 'level', // 'hasManyRoots' => true ], ]; } public static function find() { return new NestedSetQuery(get_called_class()); } }
不需要验证在 leftAttribute
、rightAttribute
、rootAttribute
和 levelAttribute
选项中指定的字段。此外,如果存在这些字段的验证规则,可能会出现问题。请检查模型规则()方法中是否有字段提到的规则。
如果要在数据库中存储单个树,可以使用 schema/schema.sql
构建数据库结构。如果您打算存储多个树,则需要 schema/schema-many-roots.sql
。
默认情况下,leftAttribute
、rightAttribute
和 levelAttribute
的值与默认数据库模式中的字段名称相匹配,因此您可以跳过这些配置。
此行为可以通过两种方式工作:每张表一个树和每张表多个树。模式是根据 hasManyRoots
选项的值选择的,默认值为 false
,表示单树模式。在多树模式下,您可以设置 rootAttribute
选项以匹配存储树的表中的现有字段。
从树中选择
以下我们将使用一个示例模型 Category
,其在数据库中的如下所示
- 1. Mobile phones
- 2. iPhone
- 3. Samsung
- 4. X100
- 5. C200
- 6. Motorola
- 7. Cars
- 8. Audi
- 9. Ford
- 10. Mercedes
在这个例子中,我们有两个树。树的根是 ID=1 和 ID=7 的记录。
获取所有根节点
$roots = Category::find()->roots()->all();
结果
与 Mobile phones 和 Cars 节点对应的 Active Record 对象数组。
获取一个节点的所有后代
$category = Category::findOne(1); if ($category) { $descendants = $category->descendants()->all(); var_dump($descendants); }
结果
与 iPhone、Samsung、X100、C200 和 Motorola 对应的 Active Record 对象数组。
获取一个节点的所有子节点
$category = Category::findOne(1); if ($category) { $descendants = $category->children()->all(); var_dump($descendants); }
结果
与 iPhone、Samsung 和 Motorola 对应的 Active Record 对象数组。
获取一个节点的所有祖先
$category = Category::findOne(5); if ($category) { $ancestors = $category->ancestors()->all(); var_dump($ancestors); }
结果
与 Samsung 和 Mobile phones 对应的 Active Record 对象数组。
获取一个节点的父节点
$category = Category::findOne(9); if ($category) { $parent = $category->parent()->one(); var_dump($parent); }
结果
与 Cars 对应的 Active Record 对象数组。
获取节点兄弟
使用 NestedSet::prev()
或 NestedSet::next()
$category = Category::findOne(9); if ($category) $nextSibling = $category->next()->one(); }
结果
与 Mercedes 对应的 Active Record 对象数组。
获取整个树
您可以使用以下标准 AR 方法获取整个树。
对于每张表一个树
Category::find()->addOrderBy('lft')->all();
对于每张表多个树
Category::find()->andWhere('root = ?', [$root_id])->addOrderBy('lft')->all();
修改树
在本节中,我们将构建与上一节中使用相同的树。
创建根节点
您可以使用 NestedSet::saveNode()
创建根节点。
$root = new Category; $root->title = 'Mobile Phones'; $root->saveNode(); $root = new Category; $root->title = 'Cars'; $root->saveNode();
结果
- 1. Mobile Phones
- 2. Cars
添加子节点
有多个方法允许您添加子节点。有关更多信息,请参阅 API。让我们使用这些方法将节点添加到我们拥有的树中
$category1 = new Category; $category1->title = 'Ford'; $category2 = new Category; $category2->title = 'Mercedes'; $category3 = new Category; $category3->title = 'Audi'; $root = Category::findOne(1); $category1->appendTo($root); $category2->insertAfter($category1); $category3->insertBefore($category1);
结果
- 1. Mobile phones
- 3. Audi
- 4. Ford
- 5. Mercedes
- 2. Cars
逻辑上,上面的树看起来并不正确。我们稍后会修复它。
$category1 = new Category; $category1->title = 'Samsung'; $category2 = new Category; $category2->title = 'Motorola'; $category3 = new Category; $category3->title = 'iPhone'; $root = Category::findOne(2); $category1->appendTo($root); $category2->insertAfter($category1); $category3->prependTo($root);
结果
- 1. Mobile phones
- 3. Audi
- 4. Ford
- 5. Mercedes
- 2. Cars
- 6. iPhone
- 7. Samsung
- 8. Motorola
$category1 = new Category; $category1->title = 'X100'; $category2 = new Category; $category2->title = 'C200'; $node = Category::findOne(3); $category1->appendTo($node); $category2->prependTo($node);
结果
- 1. Mobile phones
- 3. Audi
- 9. С200
- 10. X100
- 4. Ford
- 5. Mercedes
- 2. Cars
- 6. iPhone
- 7. Samsung
- 8. Motorola
移动一个节点使其成为新的根节点
有一个特殊的 moveAsRoot()
方法允许移动一个节点并将其变成新的根节点。在这种情况下,所有后代也会被移动。
示例
$node = Category::findOne(10); $node->moveAsRoot();
递归树遍历
Category::find()->options(); // List all the tree Category::find()->options(1); // List all category in tree with root.id=1 Category::find()->options(1, 3); // List 3 levels of category in tree with root.id=1
Fancytree 的数据格式。
Category::find()->dataFancytree(); // List all the tree Category::find()->dataFancytree(1); // List all category in tree with root.id=1 Category::find()->dataFancytree(1, 3); // List 3 levels of category in tree with root.id=1