Materialized Path for Yii 2
Materialized Path Tree trait for Yii2 ActiveRecord., (*1)
Installation
The preferred way to install this extension is through composer., (*2)
Either run, (*3)
$ composer require matperez/yii2-materialized-path
or add, (*4)
"matperez/yii2-materialized-path": "*"
to the require
section of your composer.json
file., (*5)
Migrations
Run the following command, (*6)
$ yii migrate/create create_tree_table
Open the /path/to/migrations/m_xxxxxx_xxxxxx_create_tree_table.php
file,
inside the up()
method add the following, (*7)
$this->createTable('tree', [
'id' => Schema::TYPE_PK,
'name' => Schema::TYPE_STRING.' NOT NULL',
'path' => Schema::TYPE_STRING.' NOT NULL DEFAULT \'.\'',
'position' => Schema::TYPE_INTEGER.' NOT NULL DEFAULT 0',
'level' => Schema::TYPE_INTEGER.' NOT NULL DEFAULT 0',
]);
Configuring
Configure model as follow:, (*8)
use matperez\mp\MaterializedPathBehavior;
use matperez\mp\MaterializedPathQuery;
class Tree extends \yii\db\ActiveRecord
{
/**
* @inheritdoc
*/
public function behaviors()
{
return [
[
'class' => MaterializedPathBehavior::className(),
],
];
}
/**
* @inheritdoc
*/
public function rules()
{
return [
[['position', 'level'], 'integer'],
[['path'], 'string', 'max' => 255]
];
}
/**
* Query factory
* @return MaterializedPathQuery
*/
public static function find()
{
return new MaterializedPathQuery(get_called_class());
}
}
Usage
Making a root node
To make a root node, (*9)
$root = new Tree(['name' => 'root']);
$root->makeRoot();
The tree will look like this, (*10)
- root
Appending a node as the child of another node
To prepend a node as the first child of another node, (*11)
$child = new Tree(['name' => 'child']);
$child->appendTo($root);
The tree will look like this, (*12)
- root
- child
Move node up and down among siblings
$node = Tree::findOne(['name' => 'child']);
// move node up
$node->setPosition($node->position - 1);
// move node down
$node->setPosition($node->position + 1);
Getting the root nodes
To get all the root nodes, (*13)
$roots = Tree::find()->roots()->all();
Getting children of a node
To get all the children of a node, (*14)
$root = Tree::find()->roots()->one();
foreach($root->children as $child) {
foreach($child->children as $subchild) {
// do the things with a subchild
}
}
Getting parents of a node
To get all the parents of a node, (*15)
$node = Tree::findOne(['name' => 'child']);
$parents = Tree::find()->andWhere(['id' => $node->parentIds])->all();
To get the first parent of a node, (*16)
$node = Tree::findOne(['name' => 'child']);
$parent = $node->parent();
Delete node with children
To delete node with children, (*17)
$node->delete();
Testing
./vendor/bin/codeception build
./vendor/bin/codeception run unit
Todo
more tests, mode examples, (*18)