PHPackages                             paulzi/yii2-adjacency-list - 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. paulzi/yii2-adjacency-list

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

paulzi/yii2-adjacency-list
==========================

Adjacency List Behavior for Yii2

v2.2.0(7y ago)68237.4k—8.2%12[3 issues](https://github.com/paulzi/yii2-adjacency-list/issues)14MITPHPPHP &gt;=5.4.0

Since Jul 23Pushed 7y ago8 watchersCompare

[ Source](https://github.com/paulzi/yii2-adjacency-list)[ Packagist](https://packagist.org/packages/paulzi/yii2-adjacency-list)[ RSS](/packages/paulzi-yii2-adjacency-list/feed)WikiDiscussions master Synced 1mo ago

READMEChangelogDependencies (4)Versions (15)Used By (14)

Yii2 Adjacency List Behavior
============================

[](#yii2-adjacency-list-behavior)

Implementation of adjacency list algorithm for storing the trees in DB tables.

[![Packagist Version](https://camo.githubusercontent.com/478987248640ad202ee1f0d03f4153ea38b531177275b4d4933b8cb2e14f067d/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f7061756c7a692f796969322d61646a6163656e63792d6c6973742e737667)](https://packagist.org/packages/paulzi/yii2-adjacency-list)[![Code Coverage](https://camo.githubusercontent.com/9693eb6b7345ab809a3b98640fad6dd2719d4f13ad3358a1bb7150de7cc5d1f3/68747470733a2f2f696d672e736869656c64732e696f2f7363727574696e697a65722f636f7665726167652f672f7061756c7a692f796969322d61646a6163656e63792d6c6973742f6d61737465722e737667)](https://scrutinizer-ci.com/g/paulzi/yii2-adjacency-list/?branch=master)[![Build Status](https://camo.githubusercontent.com/f7986523c8672db3b0d7213eb3e1019f47c5b3a30ee88d924b765c5efbaabc4d/68747470733a2f2f696d672e736869656c64732e696f2f7472617669732f7061756c7a692f796969322d61646a6163656e63792d6c6973742f6d61737465722e737667)](https://travis-ci.org/paulzi/yii2-adjacency-list)[![Total Downloads](https://camo.githubusercontent.com/425d8b88a4e06e3c5984eb8f15eaadb6b79ff45582109c205edb449fc79db13a/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f64742f7061756c7a692f796969322d61646a6163656e63792d6c6973742e737667)](https://packagist.org/packages/paulzi/yii2-adjacency-list)

Install
-------

[](#install)

Install via Composer:

```
composer require paulzi/yii2-adjacency-list
```

or add

```
"paulzi/yii2-adjacency-list" : "^2.2"
```

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

Migrations example
------------------

[](#migrations-example)

```
class m150722_150000_adjacency_list extends Migration
{
    public function up()
    {
        $tableOptions = null;
        if ($this->db->driverName === 'mysql') {
            // http://stackoverflow.com/questions/766809/whats-the-difference-between-utf8-general-ci-and-utf8-unicode-ci
            $tableOptions = 'CHARACTER SET utf8 COLLATE utf8_unicode_ci ENGINE=InnoDB';
        }
        $this->createTable('{{%adjacency_list}}', [
            'id'        => Schema::TYPE_PK,
            'parent_id' => Schema::TYPE_INTEGER . ' NULL',
            'sort'      => Schema::TYPE_INTEGER . ' NOT NULL',
            'name'      => Schema::TYPE_STRING . ' NOT NULL', // example field
        ], $tableOptions);
        $this->createIndex('parent_sort', '{{%adjacency_list}}', ['parent_id', 'sort']);
    }
}
```

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

[](#configuring)

```
use paulzi\adjacencyList\AdjacencyListBehavior;

class Sample extends \yii\db\ActiveRecord
{
    public function behaviors() {
        return [
            [
                'class' => AdjacencyListBehavior::className(),
            ],
        ];
    }
}
```

Optional you can setup Query for finding roots:

```
class Sample extends \yii\db\ActiveRecord
{
    public static function find()
    {
        return new SampleQuery(get_called_class());
    }
}
```

Query class:

```
use paulzi\adjacencyList\AdjacencyListQueryTrait;

class SampleQuery extends \yii\db\ActiveQuery
{
    use AdjacencyListQueryTrait;
}
```

Sortable Behavior
-----------------

[](#sortable-behavior)

This behavior attach SortableBehavior. You can use its methods (for example, reorder()).

Options
-------

[](#options)

- `$parentAttribute = 'parent_id'` - parent attribute in table schema.
- `$sortable = []` - SortableBehavior settings - see [paulzi/yii2-sortable](https://github.com/paulzi/yii2-sortable).
- `$checkLoop = false` - check loop when moving nodes (slower).
- `$parentsJoinLevels = 3` - amount of join levels, when finding ancestors.
- `$childrenJoinLevels = 3` - amount of join levels, when finding descendants.

Usage
-----

[](#usage)

### Selection

[](#selection)

**Getting the root nodes**

If you connect `AdjacencyListQueryTrait`, you can get all the root nodes:

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

**Getting ancestors of a node**

To get ancestors of a node:

```
$node11 = Sample::findOne(['name' => 'node 1.1']);
$parents = $node11->parents; // via relation unsorted
$parents = $node11->parentsOrdered; // via relation sorted
$parents = $node11->getParents()->all(); // via query
$parents = $node11->getParents(2)->all(); // get 2 levels of ancestors
```

To get parent of a node:

```
$node11 = Sample::findOne(['name' => 'node 1.1']);
$parent = $node11->parent; // via relation
$parent = $node11->getParent()->one(); // via query
```

To get root of a node:

```
$node11 = Sample::findOne(['name' => 'node 1.1']);
$root = $node11->root; // via relation
$root = $node11->getRoot()->one(); // via query
```

For get ordered list of primary keys ancestors:

```
$node11 = Sample::findOne(['name' => 'node 1.1']);
$ids = $node11->getParentsIds();
$ids = $node11->getParentsIds(3, false); // get 3 levels of ancestors primary keys with force updating from DB
```

**Getting descendants of a node**

To get all the descendants of a node:

```
$node11 = Sample::findOne(['name' => 'node 1.1']);
$descendants = $node11->descendants; // via relation unsorted
$descendants = $node11->descendantsOrdered; // via relation sorted
$descendants = $node11->getDescendants()->all(); // via query
$descendants = $node11->getDescendants(2, true)->all(); // get 2 levels of descendants and self node
```

\*Note: guaranteed order on each parent nodes, nodes of different parents can be mixed with each other and option childrenJoinLevels can change this order.

To populate `children` relations for self and descendants of a node:

```
$node11 = Sample::findOne(['name' => 'node 1.1']);
$tree = $node11->populateTree(); // populate all levels
$tree = $node11->populateTree(2); // populate 2 levels of descendants
```

To get the children of a node:

```
$node11 = Sample::findOne(['name' => 'node 1.1']);
$children = $node11->children; // via relation
$children = $node11->getChildren()->all(); // via query
```

For get ordered array of primary keys descendants per level:

```
$node11 = Sample::findOne(['name' => 'node 1.1']);
$ids = $node11->getDescendantsIds(); // get array of per-level descendants primary keys
$ids = $node11->getDescendantsIds(null, true); // get flat array of descendants primary keys
$ids = $node11->getDescendantsIds(3, false, false); // get 3 levels array of per-level descendants primary keys with force updating from DB
```

\*Note: guaranteed order on each parent nodes, nodes of different parents can be mixed with each other and option childrenJoinLevels can change this order.

**Getting the leaves nodes**

To get all the leaves of a node:

```
$node11 = Sample::findOne(['name' => 'node 1.1']);
$leaves = $node11->leaves; // via relation
$leaves = $node11->getLeaves(2)->all(); // get 2 levels of leaves via query
```

**Getting the neighbors nodes**

To get the next node:

```
$node11 = Sample::findOne(['name' => 'node 1.1']);
$next = $node11->next; // via relation
$next = $node11->getNext()->one(); // via query
```

To get the previous node:

```
$node11 = Sample::findOne(['name' => 'node 1.1']);
$prev = $node11->prev; // via relation
$prev = $node11->getPrev()->one(); // via query
```

### Some checks

[](#some-checks)

```
$node1 = Sample::findOne(['name' => 'node 1']);
$node11 = Sample::findOne(['name' => 'node 1.1']);
$node11->isRoot() - return true, if node is root
$node11->isLeaf() - return true, if node is leaf
$node11->isChildOf($node1) - return true, if node11 is child of $node1
```

### Modifications

[](#modifications)

To make a root node:

```
$node11 = new Sample();
$node11->name = 'node 1.1';
$node11->makeRoot()->save();
```

*Note: if you allow multiple trees and attribute `tree` is not set, it automatically takes the primary key value.*

To prepend a node as the first child of another node:

```
$node1 = Sample::findOne(['name' => 'node 1']);
$node11 = new Sample();
$node11->name = 'node 1.1';
$node11->prependTo($node1)->save(); // inserting new node
```

To append a node as the last child of another node:

```
$node11 = Sample::findOne(['name' => 'node 1.1']);
$node12 = Sample::findOne(['name' => 'node 1.2']);
$node12->appendTo($node11)->save(); // move existing node
```

To insert a node before another node:

```
$node13 = Sample::findOne(['name' => 'node 1.3']);
$node12 = new Sample();
$node12->name = 'node 1.2';
$node12->insertBefore($node13)->save(); // inserting new node
```

To insert a node after another node:

```
$node13 = Sample::findOne(['name' => 'node 1.3']);
$node14 = Sample::findOne(['name' => 'node 1.4']);
$node14->insertAfter($node13)->save(); // move existing node
```

To delete a node with descendants:

```
$node11 = Sample::findOne(['name' => 'node 1.1']);
$node11->delete(); // delete node, children come up to the parent
$node11->deleteWithChildren(); // delete node and all descendants
```

*Note: when deleting with delete() child nodes mixed with parent*

Reorder children:

```
$model = Sample::findOne(1);
$model->reorderChildren(true); // reorder with center zero
$model = Sample::findOne(2);
$model->reorderChildren(false); // reorder from zero
```

Updating from 1.x to 2.x
------------------------

[](#updating-from-1x-to-2x)

1. Move attributes `sortAttribute`, `step` into `sortable` attribute.
2. Change namespace from `paulzi\adjacencylist` to `paulzi\adjacencyList`.
3. Include `paulzi\yii2-sortable` (`composer update`).

###  Health Score

43

—

FairBetter than 91% of packages

Maintenance19

Infrequent updates — may be unmaintained

Popularity48

Moderate usage in the ecosystem

Community24

Small or concentrated contributor base

Maturity66

Established project with proven stability

 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.

###  Release Activity

Cadence

Every ~85 days

Recently: every ~232 days

Total

14

Last Release

2843d ago

Major Versions

v1.0.6 → v2.0.02015-12-11

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/9402208?v=4)[PaulZi](/maintainers/PaulZi)[@paulzi](https://github.com/paulzi)

---

Top Contributors

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

---

Tags

yii2adjacency list

###  Code Quality

TestsPHPUnit

### Embed Badge

![Health badge](/badges/paulzi-yii2-adjacency-list/health.svg)

```
[![Health](https://phpackages.com/badges/paulzi-yii2-adjacency-list/health.svg)](https://phpackages.com/packages/paulzi-yii2-adjacency-list)
```

###  Alternatives

[paulzi/yii2-auto-tree

Allow apply multiple tree behavior for ActiveRecord in Yii2

5053.8k6](/packages/paulzi-yii2-auto-tree)[dmstr/yii2-cookie-consent

Yii2 Cookie Consent Widget

1452.6k](/packages/dmstr-yii2-cookie-consent)

PHPackages © 2026

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