Skip to content

thomheymann/MultiTree-Behavior

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

29 Commits
 
 
 
 

Repository files navigation

CakePHP MultiTree Behavior

MultiTree is a drop-in behaviour to CakePHP's Core Tree Behavior allowing for more advanced operations and better performance on large data sets

Advantages

  • Support for root_id (This will vastly increase speed for write operations on large data sets - this is because not the whole tree has to be rewritten when updating a node but only those rows with the same root id)
  • Support for level caching
  • Easier moving of nodes (MultiTree supports full move() to any id as opposed to Core Tree's moveUp and moveDown)
  • More getter functions (easily retrieve siblings, children, parents etc.)

Caution

Use InnoDB (or a different engine that supports transactions, otherwise you have to LOCK tables manually during operations to prevent corrupted data in multi user environments)

Configuration

Example 1

The following config is meant for large trees that are often updated as well a retrieved. It keeps track of a tree that has root_id's and level caching enabled. It is ideal for e.g. Comment Trees

class Comment extends AppModel {
	var $name = 'Comment';
	var $actsAs = array(
		'MultiTree' => array(
			'root' =>'root_id',
			'level' =>'level'
			)
		);
}

Schema:

CREATE TABLE `comments` (
  `id` int(10) unsigned NOT NULL auto_increment,
  `title` varchar(128) NOT NULL default '',
  `body` text NOT NULL,
  `created` datetime default NULL,
  `modified` datetime default NULL,
  `parent_id` int(10) unsigned default NULL,
  `root_id` int(10) unsigned default NULL,
  `lft` mediumint(8) unsigned default NULL,
  `rght` mediumint(8) unsigned default NULL,
  `level` mediumint(8) unsigned default NULL,
  PRIMARY KEY  (`id`),
  KEY `rght` USING BTREE (`root_id`,`rght`,`lft`),
  KEY `lft` USING BTREE (`root_id`,`lft`,`rght`),
  KEY `parent_id` USING BTREE (`parent_id`,`created`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8

Example 2

This following config is meant for small trees that are mainly retrieved and not often updated. It keeps track of a tree without root_id's and level caching disabled. It is ideal for e.g. Category Trees Note: This would also be the config for drop in's from the core Tree Behaviour

class Category extends AppModel {
	var $name = 'Comment';
	var $actsAs = array(
		'MultiTree' => array(
			'root' => false,
			'level' => false
			)
		);
}

Schema:

CREATE TABLE `categories` (
  `id` int(10) unsigned NOT NULL auto_increment,
  `name` varchar(128) NOT NULL default '',
  `parent_id` int(10) unsigned default NULL,
  `lft` mediumint(6) unsigned default NULL,
  `rght` mediumint(6) unsigned default NULL,
  PRIMARY KEY  (`id`),
  KEY `lft` USING BTREE (`lft`),
  KEY `parent_id` USING BTREE (`parent_id`),
  KEY `rght` USING BTREE (`rght`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8

Config defaults

parent: parent_id left: lft right: rght root: root_id level: level

Traversing the tree

Get parent

Get parent based on Parent debug($this->Category->getParent(32));

Get parent based on Left/Right values debug($this->Category->getParentFromTree(32));

Get path

debug($this->Category->getPath(32));

Get level

debug($this->Category->getLevel(32));

Get children

debug($this->Category->getChildren(32));

Get direct children only: debug($this->Category->getChildren(32, true));

Get child count

debug($this->Category->getChildCount(32));

Get siblings

debug($this->Category->getSiblings(32));
debug($this->Category->getSiblings(32, true)); // Get siblings including the node itself

Get previous siblings

debug($this->Category->getPrevSiblings(32));
debug($this->Category->getPrevSiblings(32, true)); // Get previous siblings including the node itself

Get next siblings

debug($this->Category->getNextSiblings(32));
debug($this->Category->getNextSiblings(32, true)); // Get next siblings including the node itself

Get previous sibling

debug($this->Category->getPrevSibling(32));

Get next sibling

debug($this->Category->getNextSibling(32));

Insert

Insert new node as the last child of node 1 $format = array( 'name' => 'Cat', 'parent_id' => 1 ); $this->Category->save($format);

Insert new node as the next sibling of node 4

$format = array(
	'name' => 'Lion',
	'parent_id' => array('destination' => 4, 'position' => 'nextSibling')
	);
$this->Category->save($format);

Not setting a parent_id or nulling it out will insert the node as a top level (root) node

$format = array(
	'name' => 'Animal',
	'parent_id' => null
	);
$this->Category->save($format);

Move

$this->Category->move(6, 12, 'firstChild'); // Move node 6 to be the first child of node 12
$this->Category->move(6, 12, 'lastChild'); // Move node 6 to be the last child of node 12
$this->Category->move(6, 12, 'prevSibling'); // You get the idea..
$this->Category->move(6, 12, 'nextSibling');

Move node 9 up by 2 (if possible, otherwise move as high up as possible)

$this->Category->moveUp(9, 2);

Move node 9 down by 3 (if possible, otherwise move as low down as possible)

$this->Category->moveDown(9, 3);

Will make node 6 a new top level (root) node

$this->Category->move(6, null);

Delete

$this->Category->delete(25); // Same as removeFromTree(25)

This will delete node 25 and all its children

$this->Category->removeFromTree(25);

This will delete node 25 itself but if it has any children shift them one level up

$this->Category->removeFromTree(25, false);

Repair

left and right values are broken but we have valid parent_id's

$this->Category->repair('tree');

parent_id's are broken but we have valid left and right values

$this->Category->repair('parent');

About

MultiTree is a drop-in behaviour to CakePHP's Core Tree Behavior allowing for more advanced operations and better performance on large data sets

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Contributors 4

  •  
  •  
  •  
  •  

Languages