PHPackages                             wbraganca/yii2-nested-set-behavior - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Utility &amp; Helpers](/categories/utility)
4. /
5. wbraganca/yii2-nested-set-behavior

ActiveYii2-extension[Utility &amp; Helpers](/categories/utility)

wbraganca/yii2-nested-set-behavior
==================================

This extension allows you to get functional for nested set trees.

229.4k↓26.7%15[5 issues](https://github.com/wbraganca/yii2-nested-set-behavior/issues)PHP

Since Dec 1Pushed 11y ago6 watchersCompare

[ Source](https://github.com/wbraganca/yii2-nested-set-behavior)[ Packagist](https://packagist.org/packages/wbraganca/yii2-nested-set-behavior)[ RSS](/packages/wbraganca-yii2-nested-set-behavior/feed)WikiDiscussions master Synced 1mo ago

READMEChangelogDependenciesVersions (1)Used By (0)

Nested Set behavior for Yii 2
=============================

[](#nested-set-behavior-for-yii-2)

This extension allows you to get functional for nested set trees.

Installation
------------

[](#installation)

The preferred way to install this extension is through [composer](http://getcomposer.org/download/).

Either run

```
php composer.phar require wbraganca/yii2-nested-set-behavior "*"
```

or add

```
"wbraganca/yii2-nested-set-behavior": "*"
```

to the require section of your `composer.json` file.

Configuring
-----------

[](#configuring)

First you need to configure model as follows:

```
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());
    }
}
```

There is no need to validate fields specified in `leftAttribute`, `rightAttribute`, `rootAttribute` and `levelAttribute` options. Moreover, there could be problems if there are validation rules for these. Please check if there are no rules for fields mentioned in model's rules() method.

In case of storing a single tree per database, DB structure can be built with `schema/schema.sql`. If you're going to store multiple trees you'll need `schema/schema-many-roots.sql`.

By default `leftAttribute`, `rightAttribute` and `levelAttribute` values are matching field names in default DB schemas so you can skip configuring these.

There are two ways this behavior can work: one tree per table and multiple trees per table. The mode is selected based on the value of `hasManyRoots` option that is `false` by default meaning single tree mode. In multiple trees mode you can set `rootAttribute` option to match existing field in the table storing the tree.

Selecting from a tree
---------------------

[](#selecting-from-a-tree)

In the following we'll use an example model `Category` with the following in its DB:

```
- 1. Mobile phones
    - 2. iPhone
    - 3. Samsung
        - 4. X100
        - 5. C200
    - 6. Motorola
- 7. Cars
    - 8. Audi
    - 9. Ford
    - 10. Mercedes

```

In this example we have two trees. Tree roots are ones with ID=1 and ID=7.

### Getting all roots

[](#getting-all-roots)

```
$roots = Category::find()->roots()->all();
```

Result:

Array of Active Record objects corresponding to Mobile phones and Cars nodes.

### Getting all descendants of a node

[](#getting-all-descendants-of-a-node)

```
$category = Category::findOne(1);
if ($category) {
    $descendants = $category->descendants()->all();
    var_dump($descendants);
}
```

Result:

Array of Active Record objects corresponding to iPhone, Samsung, X100, C200 and Motorola.

### Getting all children of a node

[](#getting-all-children-of-a-node)

```
$category = Category::findOne(1);
if ($category) {
    $descendants = $category->children()->all();
    var_dump($descendants);
}
```

Result:

Array of Active Record objects corresponding to iPhone, Samsung and Motorola.

### Getting all ancestors of a node

[](#getting-all-ancestors-of-a-node)

```
$category = Category::findOne(5);
if ($category) {
    $ancestors = $category->ancestors()->all();
    var_dump($ancestors);
}
```

Result:

Array of Active Record objects corresponding to Samsung and Mobile phones.

### Getting parent of a node

[](#getting-parent-of-a-node)

```
$category = Category::findOne(9);
if ($category) {
    $parent = $category->parent()->one();
    var_dump($parent);
}
```

Result:

Array of Active Record objects corresponding to Cars.

### Getting node siblings

[](#getting-node-siblings)

Using `NestedSet::prev()` or `NestedSet::next()`:

```
$category = Category::findOne(9);
if ($category)
    $nextSibling = $category->next()->one();
}
```

Result:

Array of Active Record objects corresponding to Mercedes.

### Getting the whole tree

[](#getting-the-whole-tree)

You can get the whole tree using standard AR methods like the following.

For single tree per table:

```
Category::find()->addOrderBy('lft')->all();
```

For multiple trees per table:

```
Category::find()->andWhere('root = ?', [$root_id])->addOrderBy('lft')->all();
```

Modifying a tree
----------------

[](#modifying-a-tree)

In this section we'll build a tree like the one used in the previous section.

### Creating root nodes

[](#creating-root-nodes)

You can create a root node using `NestedSet::saveNode()`.

```
$root = new Category;
$root->title = 'Mobile Phones';
$root->saveNode();

$root = new Category;
$root->title = 'Cars';
$root->saveNode();
```

Result:

```
- 1. Mobile Phones
- 2. Cars

```

### Adding child nodes

[](#adding-child-nodes)

There are multiple methods allowing you adding child nodes. To get more info about these refer to API. Let's use these to add nodes to the tree we have:

```
$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);
```

Result:

```
- 1. Mobile phones
    - 3. Audi
    - 4. Ford
    - 5. Mercedes
- 2. Cars

```

Logically the tree above doesn't looks correct. We'll fix it later.

```
$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);
```

Result:

```
- 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);
```

Result:

```
- 1. Mobile phones
    - 3. Audi
        - 9. С200
        - 10. X100
    - 4. Ford
    - 5. Mercedes
- 2. Cars
    - 6. iPhone
    - 7. Samsung
    - 8. Motorola

```

Moving a node making it a new root
----------------------------------

[](#moving-a-node-making-it-a-new-root)

There is a special `moveAsRoot()` method that allows moving a node and making it a new root. All descendants are moved as well in this case.

Example:

```
$node = Category::findOne(10);
$node->moveAsRoot();
```

Recursive tree traversal
------------------------

[](#recursive-tree-traversal)

```
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
```

Data format for [Fancytree](https://github.com/wbraganca/yii2-fancytree-widget).
--------------------------------------------------------------------------------

[](#data-format-for-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
```

###  Health Score

29

—

LowBetter than 60% of packages

Maintenance15

Infrequent updates — may be unmaintained

Popularity35

Limited adoption so far

Community14

Small or concentrated contributor base

Maturity41

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

### Community

Maintainers

![](https://www.gravatar.com/avatar/3d98095370becc1cde4ab5fe5172d0063fcdf4a58612db25ae2b7da5867b067e?d=identicon)[wbraganca](/maintainers/wbraganca)

---

Top Contributors

[![wbraganca](https://avatars.githubusercontent.com/u/1946359?v=4)](https://github.com/wbraganca "wbraganca (4 commits)")

### Embed Badge

![Health badge](/badges/wbraganca-yii2-nested-set-behavior/health.svg)

```
[![Health](https://phpackages.com/badges/wbraganca-yii2-nested-set-behavior/health.svg)](https://phpackages.com/packages/wbraganca-yii2-nested-set-behavior)
```

###  Alternatives

[crodas/text-rank

Extract relevant keywords from a given text

10458.6k1](/packages/crodas-text-rank)[kunststube/rison

A PHP encoder and decoder for Rison, the compact JSON-like data format optimized for URIs.

2464.5k3](/packages/kunststube-rison)[evoweb/extender

Extending extbase domain models like a pro with extender

11260.3k6](/packages/evoweb-extender)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
