Part of the EllisLab Network
   
3 of 3
3
Nested Set library (aka MPTT, aka Hierarchy DB Trees)
Posted: 08 September 2010 08:18 PM   [ Ignore ]   [ # 21 ]  
Sr. Research Associate
Avatar
RankRankRankRankRank
Total Posts:  2549
Joined  02-19-2009

From Nested_set.php

public function setControlParams($table_name$left_column_name 'lft'$right_column_name 'rgt'$primary_key_column_name 'id'$parent_column_name 'parent_id'{
        $this
->table_name $table_name;
        
$this->left_column_name $left_column_name;
        
$this->right_column_name $right_column_name;
        
$this->primary_key_column_name $primary_key_column_name;
        
$this->parent_column_name $parent_column_name;
    
 Signature 
Profile
 
 
Posted: 29 September 2010 12:55 PM   [ Ignore ]   [ # 22 ]  
Sr. Research Associate
Avatar
RankRankRankRankRank
Total Posts:  2549
Joined  02-19-2009

I have a huge tree stored using the nested set storage method (primary id, left id, right id).  In addition, I also have a type_id which indicates what type of item each node is.  There is a certain type of node which can only be a child.

What I am trying to do with a single query is retrieve all of these children (easy since they all have the same type) but then I also want the name of one (or more) of the parents that are of a certain type (category if you will).

Think of a hierarchy of
-Country (type_id = 0)
—State (type_id = 1)
—-City (type_id = 2)

A city will always be a child node.  I am trying to get a list of cities, with their associated state name (there may be other cases where I need additional parents, such as the Country.  Basically, I want to retrieve the tree in “reverse order”.

City, State
City, State
...

This is my modified “getTreePreorder” function (which returns node level and depth info in a single query too…useful if you are using code to build html from a tree)

function getTreePreorder($node$extra_cols = array(), $type 6)
    
{
        extract
($this->_get_table_setup_data($node));
        
$extra_select $this->prep_cols('node'$extra_cols);
        
        
$q "SELECT node.`$pkcol`, node.`$leftcol`, node.`$rightcol`, $extra_select,
                (COUNT(parent.`
$leftcol`) - 1) AS depth,
                CEIL((node.`
$rightcol` - node.`$leftcol` - 1) / 2) AS child_quantity
            FROM
                `
$table` AS node,
                `
$table` AS parent
            WHERE node.`
$leftcol` BETWEEN parent.`$leftcol` AND parent.`$rightcol`
            GROUP BY node.`
$leftcol`
            HAVING node.`
$leftcol` >= $leftval AND node.`$rightcol` <= $rightval
            ORDER BY node.`
$leftcol`";
        
$query $this->db->query($q);
        
        
$treeArray = array();
        
        foreach(
$query->result_array() AS $result)
        
{            
            
if($result['type_id'<= $type)
            
{
                $treeArray[] 
$result;
            
}
        }
        
        
return array(  "result_array"  => $treeArray,
                       
"prev_left"     => $node[$leftcol],
                       
"prev_right"    => $node[$rightcol],
                       
"level"         => -2);
    

Here are 2 helper functions used above:

//helper function gets the default column names and protects identifiers, as well as any optional column names provided in $extra_cols
    //$type can be 'node' or 'parent', depending on what is needed for the query
    
function prep_cols($type 'node'$extra_cols = array())
    
{
        $cols 
= array();
        
$extra_select '';
        
        foreach(
$this->default_col_names as $d)
        
{
            $cols[] 
"$type.`$d`";
        
}
        
foreach($extra_cols as $d)
        
{
            $cols[] 
"$type.`$d`";
        
}
        $extra_select 
implode(', '$cols);
           
//if( ! empty($extra_select)) $extra_select = ', ' . $extra_select . ', ';
           
           
return $extra_select;
    
}
    
    
//helper function to get the needed table and column info for various db queries.
    //returned array is meant to be extract()ed internally to use the variables in building SQL
    
function _get_table_setup_data($node)
     
{
         
return array(
             
'table'      =>       $this->table_name,
             
'pkcol'         =>          $this->primary_key_column_name,
            
'leftcol'    =>       $this->left_column_name,
            
'rightcol'   =>       $this->right_column_name,
              
'pkval'         =>    (int) $node[$this->primary_key_column_name],
            
'leftval'    => (int) $node[$this->left_column_name],
            
'rightval'   => (int) $node[$this->right_column_name]
        
);
     

And this is a piece of code that will retrieve the siblings of a given node.  This does what I need, but I need it incorporated into my original query or else this query will get executed several thousand times. (Also great for creating breadcrumbs).

//retrieve ancestor nodes (branch) of the hierarchy for a supplied node, or a specific type of node from the branch.
    //if $hierarchy_type_id contains id of specific hierarchy type,
    //it will return only that node instead of the entire branch.
    //eg. enter the type id for state to find out what state a node is in.
    
function get_branch($node$hierarchy_type_id ''$extra_cols = array())
    
{
        extract
($this->_get_table_setup_data($node));
        
        
$extra_select $this->prep_cols('parent'$extra_cols);
        
        
$having = (empty($hierarchy_type_id)) ? '' " HAVING parent.`type_id` = $hierarchy_type_id ";
        
        
$q "SELECT
                
$extra_select
            FROM
                `
$table` AS node,
                `
$table` AS parent
            WHERE
                node.`
$leftcol` BETWEEN parent.`$leftcol` AND parent.`$rightcol` AND
                node.`
$pkcol` = $pkval
            
$having
            ORDER BY
                parent.`
$leftcol`";
        
        return 
$this->db->query($q)->result_array();
    

Any guidance would be greatly appreciated.  I’m not very good with these more complex queries.

 Signature 
Profile
 
 
Posted: 08 January 2011 04:49 PM   [ Ignore ]   [ # 23 ]  
Grad Student
Avatar
Rank
Total Posts:  42
Joined  10-29-2009

Hello, just wondering if anyone has uploaded the most recent version of this wonderful library class to this thread.  I only found the one attached file on the first post of this thread.  Is that the most current version?

Thanks in advance.

Profile
 
 
Posted: 10 February 2011 12:45 AM   [ Ignore ]   [ # 24 ]  
Summer Student
Total Posts:  1
Joined  02-09-2011

Is thunder’s version most complete? there isn’t anything else thats complete, library or model class for nested sets.

TIA.

Profile
 
 
Posted: 08 March 2011 06:24 PM   [ Ignore ]   [ # 25 ]  
Summer Student
Total Posts:  5
Joined  04-25-2009

in my controller(i added library on autoload):     
$this->nested_set->setControlParams(‘nested_set_tree’); 
$root_nodes1 = $this->nested_set->getRootNodes();
i SEE this error “:
Fatal error: Call to undefined method CI_DB_mysql_driver::getwhere() in C:\wamp\www\application\libraries\Nested_set.php on line 322”


ANDDD
how i can add a new data to database this system?

Profile
 
 
Posted: 08 March 2011 07:29 PM   [ Ignore ]   [ # 26 ]  
Sr. Research Associate
Avatar
RankRankRankRankRank
Total Posts:  4115
Joined  11-04-2008

Find another solution.

Appearantly the nested sets post in the wiki is very dated, the getwhere() method was deprecated a long time ago, and is no longer present in CI 2.x.

You could have a look at Datamapper, it includes a nested sets extension (http://datamapper.wanwizard.eu/pages/extensions/nestedsets.html) which is still in beta, but seems to work just fine…

 Signature 

WanWizard.eu | Modular CI, an HMVC solution | DataMapper ORM

Profile
 
 
Posted: 09 May 2012 08:15 PM   [ Ignore ]   [ # 27 ]  
Summer Student
Total Posts:  1
Joined  03-16-2012

Anyone can upload the zip file of this library ?
The download link in first page doesn’t work.

BTW, switch it back to a model is a good idea.

Profile
 
 
Posted: 10 May 2012 10:11 AM   [ Ignore ]   [ # 28 ]  
Lab Assistant
Avatar
RankRank
Total Posts:  168
Joined  12-12-2010
tinsn - 09 May 2012 08:15 PM

Anyone can upload the zip file of this library ?
The download link in first page doesn’t work.

BTW, switch it back to a model is a good idea.

You can use Zebra MPTT http://stefangabos.ro/php-libraries/zebra-mptt/ and adapt it to CodeIgniter, i have done it so i know it works, but i’m not using mptt anymore.

Profile
 
 
   
3 of 3
3