Skip to content
forked from banks/sprig-mptt

An MPTT extension for shadowhand's Sprig modelling system for Kohana

Notifications You must be signed in to change notification settings

ascseb/sprig-mptt

 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

31 Commits
 
 
 
 
 
 

Repository files navigation

Sprig_MPTT

A Modified Preorder Tree Traversal extension for Sprig.

This extension is largely based on the Kohana 2.x ORM_MPTT module developed by Mathew Davies and Kiall Mac Innes. All the hardwork was done by them!

Differences From ORM_MPTT

The vast majority of functionality is the same, including the same function names etc.

The only major changes externally is that new_scope() has been renamed to insert_as_new_root() to keep things more consistent and to work better with Sprig's validation, and that parents() is renamed to ancestors().

Also, as all fields have to be specified in Sprig, the four MPTT columns are defined by Sprig_Field_MPTT_* objects. They are optional though, with Sprig_MPTT automatically creating default MPTT fields if none are specified (see below). Sprig_MPTT also defines foreign fields for parent, ancestors, descendants, children etc. for you, see public $related to change the plural used to "load with" ("children" could become "sub_categories" for example, for overwriting only a select few values use _init())

There may be other minor differences or bugs introduced. I'll try to fix them or point them out as I find them.

Quick Start

Defining a Model

To create a Sprig_MPTT model, you need to create a normal Sprig model but extend Sprig_MPTT instead of Sprig.

Your table must have the four MPTT columns (left, right, level and scope) since there are reserved word clashes in most database systems, the default and recommended naming of these columns is lft, rgt, lvl and scope respectively. All four columns are integers.

If the columns in your database are named as suggested, you do not need to manually define the fields in your _init() method as Sprig_MPTT will create them for you. If you need to change the name of any of these columns you can do so by specifying them as normal in your _init method. Example:

class Model_Example extends Sprig_MPTT
{
	protected function _init()
	{
		$this->_fields += array(
			'id' => new Sprig_Field_Auto,
			'name' => new Sprig_Field_Char,
			'my_left' => new Sprig_Field_MPTT_Left,
			'my_right' => new Sprig_Field_MPTT_Right,
			'my_level' => new Sprig_Field_MPTT_Level,
			'my_scope' => new Sprig_Field_MPTT_Scope,
		);
	}
}

You only need to define the MPTT fields for which the column name differs from the defaults above, the rest are created automatically.

Setting up a Tree

The major difference between Sprig and Sprig_MPTT models is that you can no longer use the create() method. This is to stop inserts invalidating the MPTT tree.

To create a new MPTT record, you need to use one of the insert_* methods.

Before you create any other records in a tree, you need to create the root record for the tree. This can be done like:

// Get the root node for the scope 1
$root = Sprig::factory('test')->root($root, 1)->load($root);

// If the root node isn't loaded, we must create it before we can do anything else with the tree in scope 1
if ( ! $root->loaded())
{
	$root->name = 'Root Node'; // All object properties which are required must be specified otherwise Validation will fail
	
	try
	{
		$root->insert_as_new_root(1);
	}
	catch (Validate_Exception $e)
	{
		// Handle the bad data
	}
}

After that, you can use the scope tree with any of the other methods in the class.

Inserting Nodes

Nodes can be inserted (created) using:

$model->insert_as_first_child($target);
$model->insert_as_last_child($target);
$model->insert_as_next_sibling($target);
$model->insert_as_prev_sibling($target);

Where $target is either another (loaded) Sprig_MPTT object or the primary key value (id) of one. They do exactly what you would expect.

Moving a node

Similarly, exisiting nodes can be moved in the tree using:

$model->move_to_first_child($target);
$model->move_to_last_child($target);
$model->move_to_next_sibling($target);
$model->move_to_prev_sibling($target);

These methods will return false if you try to move a node into itself or one of it's descendants.

Other functions

Deleting a node is the same as in Sprig. As is pretty much everything else.

Accessing Tree Relationships

A model's related nodes can be accessed using:

$model->parent;		// returns Sprig object for direct parent
$model->ancestors;	// returns DB result for all ancestors
$model->descendants;	// returns DB result containting all descendants
$model->children;	// returns DB result containing direct children
$model->first_child;	// returns Sprig object for first child
$model->last_child;	// returns Sprig object for last child
$model->siblings;	// returns DB result containing all sibling nodes
$model->leaves;		// returns DB result containing all children who have no further children
$model->root;		// retruns root node of current scope tree

To specify ordering, constraining query results, or whether to include the current object in the result, use the correspondingly named methods parents(), children() etc.

NOTE: Using the methods returns the SQL query rather then the sprig object, so you'll have to load the query back into a new Sprig object in order to obtain the results.

Adding query constraints.

Using the selectors described in the previous section will return the sprig objects which unlike ORM, contain no methods for constraining SQL results. That is why the selector methods return the raw queries, whilst the selector properties return the Sprig objects.

For example, to select all children of the current 'foo' model with the field 'bar' being equal to 'baz', you would type:

$result = Sprig::factory('foo', array('bar' => 'baz'))->children($result)->load($result, FALSE);

The use of Sprig_MPTT over Sprig is irrelevent, i've only done that for the code's readability.

TODO

  • There are some known limitations such as you can only use an integer as a scope -- this may or may not warrant further work
  • Fix the any bugs that are found!

About

An MPTT extension for shadowhand's Sprig modelling system for Kohana

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published