Nested Set benefits with Adjacency List effort. Retrieve the children, counts, levels, paths, trees, nests, and leaves from your category nodes.
The BootPress Hierarchy Component bridges the gap between Adjacency lists and the Nested Set Model, so that you can have both the simplicity of Adjacency lists, with the power and efficiency of Nested sets.
The $db $table must have the following fields:
All you need to worry about is the $id and 'parent'. This class will take care of the rest.
A BootPress\Database\Component instance.
The name of the database's hierarchical table. Saved in the $hier->table
private property.
The database table's id column. Saved in the $hier->id
private property.
use BootPress\Database\Component as Database;
use BootPress\Hierarchy\Component as Hierarchy;
$db = new Database('sqlite::memory:');
$db->exec(array(
'CREATE TABLE category (',
' id INTEGER PRIMARY KEY,',
' name TEXT NOT NULL DEFAULT "",',
' parent INTEGER NOT NULL DEFAULT 0,',
' level INTEGER NOT NULL DEFAULT 0,',
' lft INTEGER NOT NULL DEFAULT 0,',
' rgt INTEGER NOT NULL DEFAULT 0',
')',
));
if ($stmt = $db->insert('category', array('id', 'name', 'parent'))) {
$db->insert($stmt, array(1, 'Electronics', 0));
$db->insert($stmt, array(2, 'Televisions', 1));
$db->insert($stmt, array(3, 'Tube', 2));
$db->insert($stmt, array(4, 'LCD', 2));
$db->insert($stmt, array(5, 'Plasma', 2));
$db->insert($stmt, array(6, 'Portable Electronics', 1));
$db->insert($stmt, array(7, 'MP3 Players', 6));
$db->insert($stmt, array(8, 'Flash', 7));
$db->insert($stmt, array(9, 'CD Players', 6));
$db->insert($stmt, array(10, '2 Way Radios', 6));
$db->insert($stmt, array(11, 'Apple in California', 1));
$db->insert($stmt, array(12, 'Made in USA', 11));
$db->insert($stmt, array(13, 'Assembled in China', 11));
$db->insert($stmt, array(14, 'iPad', 13));
$db->insert($stmt, array(15, 'iPhone', 13));
$db->close($stmt);
}
$hier = new Hierarchy($db, 'category', 'id');
Refreshes the database table's 'level', 'lft', and 'rgt' columns. This should be called any time you insert into, or delete from your hierarchical table.
The table's field name you would like to base the order on. The default is to use the $hier->id
field.
$hier->refresh();
Delete a node and all of it's children from your hierarchical table.
The $hier->id
of the node.
Either false
if nothing was affected, or an array()
of deleted ids.
print_r($hier->delete(11)); // array(11, 12, 13, 14, 15)
$hier->refresh(); // don't forget to do this!
Get the id of a given path.
The $hier->table
's column name.
The $field values to drill down.
Either false
if no result found, or an integer
id.
echo $hier->id('name', array('Electronics')); // 1
echo $hier->id('name', array('Electronics', 'Portable Electronics', 'CD Players')); // 9
echo $hier->id('name', array('Electronics', 'Apple in California')); // false
Retrieve a single path.
The $hier->table
's column name.
Of the $field.
The column(s) that you want to return. The default is the $field you specify.
An array of $hier->id
(keys) and $column (values).
var_export($hier->path('name', 'Flash'));
array(
1 => 'Electronics',
6 => 'Portable Electronics',
7 => 'MP3 Players',
8 => 'Flash',
)
var_export($hier->path('id', 9, array('level', 'name', 'parent')));
array(
1 => array('level' => 0, 'name' => 'Electronics', 'parent' => 0),
6 => array('level' => 1, 'name' => 'Portable Electronics', 'parent' => 1),
9 => array('level' => 2, 'name' => 'CD Players', 'parent' => 6),
)
Find the immediate subordinates of a node ie. no grand children.
The $hier->id
of the node.
The column(s) that you want to return.
An array of $hier->id
(keys) and $column (values).
var_export($hier->children(6, 'name'));
array(
7 => 'MP3 Players',
9 => 'CD Players',
10 => '2 Way Radios',
)
var_export($hier->children(6, array('level', 'name')));
array(
7 => array('level' => 2, 'name' => 'MP3 Players'),
9 => array('level' => 2, 'name' => 'CD Players'),
10 => array('level' => 2, 'name' => '2 Way Radios'),
)
Find all the nodes at a given level.
The level you want, starting at 0.
A single column string, or an array of columns that you want to return.
An array of $hier->id
(keys) and $column (values).
var_export($hier->level(2, array('parent', 'name')));
array(
3 => array('parent' => 2, 'name' => 'Tube'),
4 => array('parent' => 2, 'name' => 'LCD'),
5 => array('parent' => 2, 'name' => 'Plasma'),
7 => array('parent' => 6, 'name' => 'MP3 Players'),
9 => array('parent' => 6, 'name' => 'CD Players'),
10 => array('parent' => 6, 'name' => '2 Way Radios'),
)
Aggregate the total records in a table for each tree node.
The database table to aggregate the records from.
The $table column that corresponds with the $hier->id
.
A specific node you may be looking for.
The total count(s).
$db->exec(array(
'CREATE TABLE products (',
' id INTEGER PRIMARY KEY,',
' category_id INTEGER NOT NULL DEFAULT 0,',
' name TEXT NOT NULL DEFAULT ""',
')',
));
if ($stmt = $db->insert('products', array('category_id', 'name'))) {
$db->insert($stmt, array(3, '20" TV'));
$db->insert($stmt, array(3, '36" TV'));
$db->insert($stmt, array(4, 'Super-LCD 42"'));
$db->insert($stmt, array(5, 'Ultra-Plasma 62"'));
$db->insert($stmt, array(5, 'Value Plasma 38"'));
$db->insert($stmt, array(7, 'Power-MP3 128mb'));
$db->insert($stmt, array(8, 'Super-Shuffle 1gb'));
$db->insert($stmt, array(9, 'Porta CD'));
$db->insert($stmt, array(9, 'CD To go!'));
$db->insert($stmt, array(10, 'Family Talk 360'));
$db->close($stmt);
}
echo $hier->counts('products', 'category_id', 2); // 5 (Televisions - category_id's 3, 4, and 5)
var_export($hier->counts('products', 'category_id'));
array( // id => count
1 => 10, // Electronics
2 => 5, // Televisions
3 => 2, // Tube
4 => 1, // LCD
5 => 2, // Plasma
6 => 5, // Portable Electronics
7 => 2, // MP3 Players
8 => 1, // Flash
9 => 2, // CD Players
10 => 1 // 2 Way Radios
)
Retrieve a full tree, or any parts thereof.
The column(s) that you want to return.
The $hier->table
's column name, or the $having depth below if not specifying a $value.
Of the $field. The depths will be relative to this now.
The desired depth of the nodes eg. 'depth > 1'
An array of $hier->id
(keys) and $column (values), including 'parent' and 'depth' info.
var_export($hier->tree('name'));
array(
1 => array('name' => 'Electronics', 'parent' => 0, 'depth' => 0),
2 => array('name' => 'Televisions', 'parent' => 1, 'depth' => 1),
3 => array('name' => 'Tube', 'parent' => 2, 'depth' => 2),
4 => array('name' => 'LCD', 'parent' => 2, 'depth' => 2),
5 => array('name' => 'Plasma', 'parent' => 2, 'depth' => 2),
6 => array('name' => 'Portable Electronics', 'parent' => 1, 'depth' => 1),
7 => array('name' => 'MP3 Players', 'parent' => 6, 'depth' => 2),
8 => array('name' => 'Flash', 'parent' => 7, 'depth' => 3),
9 => array('name' => 'CD Players', 'parent' => 6, 'depth' => 2),
10 => array('name' => '2 Way Radios', 'parent' => 6, 'depth' => 2),
)
var_export($hier->tree('name', 'id', 6));
array(
6 => array('name' => 'Portable Electronics', 'parent' => 1, 'depth' => 0),
7 => array('name' => 'MP3 Players', 'parent' => 6, 'depth' => 1),
8 => array('name' => 'Flash', 'parent' => 7, 'depth' => 2),
9 => array('name' => 'CD Players', 'parent' => 6, 'depth' => 1),
10 => array('name' => '2 Way Radios', 'parent' => 6, 'depth' => 1),
)
var_export($hier->tree('name', 'depth > 2',));
array(
8 => array('name' => 'Flash', 'parent' => 7, 'depth' => 3),
)
Create a multi-dimensional array using the first value of each tree array.
As retrieved from $this->tree()
.
$tree = $hier->tree('name', 'id', 6);
var_export($hier->lister($tree));
array(
'Portable Electronics' => array(
'MP3 Players' => array(
'Flash',
),
'CD Players',
'2 Way Radios',
),
)
Create a multi-dimensional array using $this->id
's id of each tree array.
As retrieved from $this->tree()
.
$tree = $hier->tree('name', 'id', 6);
var_export($hier->nestify($tree));
array(
6 => array(
7 => array(
8 => array(),
),
9 => array(),
10 => array(),
),
)
Flatten a nested tree.
As retrieved from $this->nestify()
.
$tree = $hier->tree('name', 'id', 6);
$nest = $hier->nestify($tree);
var_export($hier->flatten($nest));
array(
array(6, 7, 8),
array(6, 9),
array(6, 10),
)
Add the following to your composer.json
file.
{
"require": {
"bootpress/hierarchy": "^1.0"
}
}
<?php
use BootPress\Database\Component as Database;
use BootPress\Hierarchy\Component as Hierarchy;
$db = new Database('sqlite::memory:');
$db->exec(array(
'CREATE TABLE category (',
' id INTEGER PRIMARY KEY,',
' name TEXT NOT NULL DEFAULT "",',
' parent INTEGER NOT NULL DEFAULT 0,',
' level INTEGER NOT NULL DEFAULT 0,',
' lft INTEGER NOT NULL DEFAULT 0,',
' rgt INTEGER NOT NULL DEFAULT 0',
')',
));
if ($stmt = $db->insert('category', array('id', 'name', 'parent'))) {
$db->insert($stmt, array(1, 'Electronics', 0));
$db->insert($stmt, array(2, 'Televisions', 1));
$db->insert($stmt, array(3, 'Tube', 2));
$db->insert($stmt, array(4, 'LCD', 2));
$db->insert($stmt, array(5, 'Plasma', 2));
$db->insert($stmt, array(6, 'Portable Electronics', 1));
$db->insert($stmt, array(7, 'MP3 Players', 6));
$db->insert($stmt, array(8, 'Flash', 7));
$db->insert($stmt, array(9, 'CD Players', 6));
$db->insert($stmt, array(10, '2 Way Radios', 6));
$db->insert($stmt, array(11, 'Apple in California', 1));
$db->insert($stmt, array(12, 'Made in USA', 11));
$db->insert($stmt, array(13, 'Assembled in China', 11));
$db->insert($stmt, array(14, 'iPad', 13));
$db->insert($stmt, array(15, 'iPhone', 13));
$db->close($stmt);
}
$hier = new Hierarchy($db, 'category', 'id');
The $db table must have the 'parent', 'level', 'lft', and 'rgt' fields for everything to work. All you need to worry about is the 'id' and 'parent'. This class will take care of the rest. When you get things all set up, and whenever you make any changes:
$hier->refresh();
That will create and update the nested sets info from your 'id' and 'parent' fields. To delete a node and all of it's children you can:
print_r($hier->delete(11)); // array(11, 12, 13, 14, 15)
$hier->refresh(); // don't forget to do this!
You just removed "Apple in California", and everything associated with them.
// Get the id of a given path
echo $hier->id('name', array('Electronics', 'Portable Electronics', 'CD Players')); // 9
// Retrieve a single path
print_r($hier->path('name', 'Flash'));
/*
array(
1 => 'Electronics',
6 => 'Portable Electronics',
7 => 'MP3 Players',
8 => 'Flash',
)
*/
// Aggregate the total records in a table for each tree node
$db->exec(array(
'CREATE TABLE products (',
' id INTEGER PRIMARY KEY,',
' category_id INTEGER NOT NULL DEFAULT 0,',
' name TEXT NOT NULL DEFAULT ""',
')',
));
if ($stmt = $db->insert('products', array('category_id', 'name'))) {
$db->insert($stmt, array(3, '20" TV'));
$db->insert($stmt, array(3, '36" TV'));
$db->insert($stmt, array(4, 'Super-LCD 42"'));
$db->insert($stmt, array(5, 'Ultra-Plasma 62"'));
$db->insert($stmt, array(5, 'Value Plasma 38"'));
$db->insert($stmt, array(7, 'Power-MP3 128mb'));
$db->insert($stmt, array(8, 'Super-Shuffle 1gb'));
$db->insert($stmt, array(9, 'Porta CD'));
$db->insert($stmt, array(9, 'CD To go!'));
$db->insert($stmt, array(10, 'Family Talk 360'));
$db->close($stmt);
}
print_r($hier->counts('products', 'category_id'));
/*
array( // id => count
1 => 10, // Electronics
2 => 5, // Televisions
3 => 2, // Tube
4 => 1, // LCD
5 => 2, // Plasma
6 => 5, // Portable Electronics
7 => 2, // MP3 Players
8 => 1, // Flash
9 => 2, // CD Players
10 => 1 // 2 Way Radios
)
*/
// Retrieve a tree
$tree = $hier->tree('name', 'id', 6);
print_r($tree);
/*
array(
6 => array('name' => 'Portable Electronics', 'parent' => 1, 'depth' => 0),
7 => array('name' => 'MP3 Players', 'parent' => 6, 'depth' => 1),
8 => array('name' => 'Flash', 'parent' => 7, 'depth' => 2),
9 => array('name' => 'CD Players', 'parent' => 6, 'depth' => 1),
10 => array('name' => '2 Way Radios', 'parent' => 6, 'depth' => 1),
)
*/
// Flatten it
$nest = $hier->nestify($tree);
var_export($hier->flatten($nest));
array(
array(6, 7, 8),
array(6, 9),
array(6, 10),
)