NestedNodes Class Manual By Shadi Ali
Preface:
Finally the Best Class for Nesting any MySQL table records is HERE!!
Nesting any MySQL table records to be parents and childrens was never that easy!
Why would you use this class?
What is Position Chain Idea..?
before writing this class, providing a solution for a nested nodes was done with two popular ways, one of them is to define a database field to carry the parent node id .. and the other way was using SQL Joins.
with all respect to both ways, I didn't find it easy to deal with the rows after applying one of the ways so that's why i thought in the Position Chain Idea.
in the Position Chain , I store the node family tree/chain in the field called position .. the tree start from the first father ID till the node itself ID .. the IDs are separated with right Arrow >
look at this
1>3>5>88>
from the first look you are able to determine that this row is in the 4th level, and his parent ID is 5 ... till the first father which have the ID 1.
OK, is the only benefit from such idea to make it easy to read the node family tree when looking to records ..??
Of course this is a great benefit, but it's not the only benefit .. this Position Chain facilitate the manipulation of the records!
to get a the family tree just use explode(">", "1>3>5>88>") to have the family into array .. print it as you want!!
<?php
$nodes = new nodes('categories');
$positionChain = "1>3>5>88"; // i'm just wrtiting any example position
$positions = explode(">"
, $positionChain);
array_pop($positions); // just remove the last free element.
foreach($positions as $id){
$category = $nodes->fetch($id);
print_r($category);
}
ok any other benefit than exploding the position to know the family till the roots ??
sure, what about getting the node depth level from just counting the exploded array!!
<?php
$positionChain = "1>3>5>88"; // I'm just writing any example position
$positions = explode(">"
, $positionChain);
$depth = count($positions) -1; // just remove the last free element.
echo "i'm the node with the id 88 and in the ".$depth"th level!";
?>
ok enough explaining the idea, you will touch the benefits yourself when you start to write the first line of your codes using the NestedNodes class!
before reading this manual you may want to check the class in action .. just put the file called node_test.php with the nodes.class.php into a directory on a running webserver ... execute our categories table query , modify the mysql connection values in the first lines of nodes_test.php file .. call it from your browser (ie. http://localhost/nodes/nodes_test.php ) .. and here you go!
Manual Start
MySQL Table:
This class runs on any table which have only three essential columns
( id => primary key usually bigint)
( position => holds the position chain .. usually varchar(255) to hold about 50 nested levels).
( ord => holds the items display order in its level )
The essential table.
CREATE TABLE `nodes` (
`id` BIGINT NOT NULL AUTO_INCREMENT ,
`position` VARCHAR( 255 ) NOT NULL ,
`ord` int NOT NULL ,
-- add your fields here
-- ie -> `node_name` varchar(160),
-- add your fields here
PRIMARY KEY ( `id` ) ,
INDEX ( `position` )
);
lets take an example of an articles table:
CREATE TABLE `articles` (
`id` BIGINT NOT NULL AUTO_INCREMENT ,
`position` VARCHAR( 255 ) NOT NULL ,
`ord` int NOT NULL ,
`article_title` VARCHAR( 255 ) NOT NULL,
`article_text` text,
PRIMARY KEY ( `id` ) ,
INDEX ( `position` )
);
and our working example table , the categories table :-)
CREATE TABLE `categories` (
`id` BIGINT NOT NULL AUTO_INCREMENT ,
`position` VARCHAR( 255 ) NOT NULL ,
`ord` int NOT NULL ,
`c_name` VARCHAR( 255 ) NOT NULL,
`c_desc` tinytext,
PRIMARY KEY ( `id` ) ,
INDEX ( `position` )
);
Class Variables:
Here I'm going to explain the class variables
$table_name
this is the MySQL table name which you want the class to work on.
usage:
<? $nodes->table_name = 'categories' ?>
to initialize the table name ,
or simply enter the table name when initializing the class
<? $nodes= new nodes('categories') ?>
$table_fields
This variable holds the default default names for the three mandatory fields (id , position , ord).
its an array of 3 elements , if you want to customize it:
<?
$nodes->table_fields['id'] = 'category_id' ;
$nodes->table_fields['position'] = 'category_position' ;
$nodes->table_fields['ord'] = 'category_order' ;
?>
$sql_condition
This variable set an extra sql condition to affect all the queries used in the class.
for example, if you want to make a table for the site navigation menus ... you have a menu in the header .. and a menu in the footer .. both menus use the same table fields so its not wise to make two tables for each one, just add a field and lets call it "menu_place" and when using the class to work with the header menu:
<?
$nodes->sql_condition = "AND menu_place = 'header' " ;
?>
now the class only works on the rows which have the field value = header :-) ... isn't that easy ?!
$HtmlTree
This variable holds the default HTML template for the HTML list, It is used only when you call the html_output($id, $clickable=false) method ... its an array and contains 12 elements required to build the nested html list
modify the template value as you want , but always remmeber to put the your columns between square brackets [] ( ie. <a href="?id=[id]">[article_name]</a> ) [article_name] will be replaced with the actual article name from your database, same goes on [id].
default value for the $HtmlTree Variable:
look at the following example menu figure to understand how the template is parsed by the class html_output() method.
$HtmlRow
The previous HtmlTree variable was about printing standard nested Unobtrusive <ul> menu... OK. another kind of a popular type of menu but it doesn't follow a standard is the row menu, You>Are>Here like menus ( i.e Home > Programming >PHP ) , this method isn't forgotten in this class.
This variable holds the default HTML template for the row HTML list, It is used only when you call the html_row_output($id) method ... its an array and contains 5 elements required to build the row html menu.
modify the template value as you want , but always remember to put the your database columns between square brackets [] ( ie. <a href="?id=[id]">[article_name]</a> ) [article_name] will be replaced with the actual article name from your database, same goes on [id].
default value for the $HtmlRow Variable:
Sounds easy to understand ? .. if not yet , note to check the nodes_test.php usage example file
Main Functions/Methods:
add_new($parent_id , $fields=array()):
this method is used to insert new node to the structure , it takes 2 params as the following:
$parent : every node should have a parent node, if it doesn't then it will be a root node ... this variable holds the parent node ID or assign zero.
$fields: array containing your column names as keys and data as values to be inserted into the MySQL table.
example on method usage:
update($node_id , $parent_id , $fields=array()):
this method is used to update existing node , it takes 5 params as the following:
$id: the ID of node which you want to update.
$parent : every node should have a parent node, if it doesn't then it will be a root node ... this variable holds the parent node ID otherwise assign zero, to prevent from a change pass the current node parent when updating :-)
$fields: array containing your column names as keys and data as values
example on method usage:
delete($node_id):
this method is used to delete existing node and all sub-nodes below it
it returns the deleted nodes IDs as array , so you could do later operations (i.e delete linked images or files )
needs 1 params as the following:
$id: the ID of node which you want to delete.
example on method usage:
order_node($id , $new_order):
this method is used to change the node display order inside its level.
to move the order up , just pass the current order minus 1 as the $new_order
, same goes when moving down .. just add 1 to the current order.
needs 2 params as the following:
$id: the ID of node which you want to re-order.
$new_order: the new_order of the node .. don't care about giving wrong orders, the class handle it well!
example on method usage:
$mynode = $nodes->fetch("4");
// lets move mynode up
$nodes->order_node($mynode['id'] , $mynode['ord'] - 1);
// lets move mynode down
$nodes->order_node($mynode['id'] , $mynode['ord'] + 1);
// lets move mynode to the be the first in its list
$nodes->order_node($mynode['id'] , 1);
// lets move mynode to the be the last in its list
$nodes->order_node($mynode['id'] , -1 );
build_list($id , $clickable):
this method is used to return an array with the categories,it takes 2 params as the following:
$id: if you want to display an expanded list below a specific node fill its ID , otherwise the list will be expanded from the roots.
$collapesd: determine if the expanding level to be one-level only or unlimited. ( default is FALSE )
examples on method usage:
General Usage
I'm going to explain some ways to use this method based on the following list example node_Name(ID)
-Root1 (1)
-Sub1-1 (2)
-Sub1-1-1 (3)
-Sub1-1-2 (4)
-Sub1-2 (5)
-Sub1-2-1 (6)
-Root2 (7)
-Sub2-1 (8)
OK lets start ...
To expand a root:
-Root1 (1)
-Sub1-1 (2)
-Sub1-1-1 (3)
-Sub1-1-2 (4)
-Sub1-2 (5)
-Sub1-2-1 (6)
+Root2
To display/open one-level only of expanded root:
-Root1 (1)
+Sub1-1 (2)
+Sub1-2 (5)
+Root2
To display/open one-level only of a child node:
-Root1 (1)
-Sub1-1 (2)
+Sub1-1-1 (3)
+Sub1-1-2 (4)
+Sub1-2 (5)
+Root2
And finally to display the full expanded list:
-Root1 (1)
-Sub1-1 (2)
-Sub1-1-1 (3)
-Sub1-1-2 (4)
-Sub1-2 (5)
-Sub1-2-1 (6)
-Root2 (7)
-Sub2-1 (8)
browse_by_id($id):
this function returns an array of sub-nodes within a specific node .. and takes the parent node ID as a param $id
fetch($id):
very useful function.
this function returns the node info from database as array.. and takes the node ID as a param $id
html_output($id , $clickable = false):
this function returns the HTML list output, and takes the selected node ID as a param or it will print the roots list.
you can modify the template of the list by modifying the $HtmlTree variable as shown above.
this function is useful when you want to print a Clickable list too depending on the selected node ID. (same as build_list() method above)
html_row_output($id):
this function returns the row HTML list (You>Are>Here like menu) output, and takes the selected node ID as a param or it will print the roots list.
you can modify the template of the list by modifying the $HtmlRow variable as showen above.
count_nodes:
this function returns how many sub nodes in below the given node ID, and takes parent node ID as a param.
Manual End.
Thank You.
Shadi Shaban
Feb/03/2007