Parent-child associations using the "Nested Set Model"
The "Nested Set Model" is a method for organizing records in a tree like manner. It use two columns to model the containment. Each record is given a left and a right value. It is faster in read mode than the commonly used "Adjacency List Model" which make use of a parent primary key value.
This functionnality introduce new methods to the records who defined the key "hierarchical" in their "meta_field" property array. Each of those methods may be call in 2 different ways. Either though the "hierarchy" property of the record which return a "PorteHierarchy" object or by using a shortcut which skip this property.
Simple Exemple
Command: "php samples/associations/parent-child/simple-exemple.php"
class File extends PorteRecord{
public $meta_table = array(
'hierarchical' => true
);
public $meta_fields = array(
'title' => array()
);
}
$parent = new File();
$parent->setTitle('Root file');
$child1 = new File();
$child1->setTitle('Child 1');
$parent->addChild($child1);
$child2 = new File();
$child2->setTitle('Child 2');
$parent->addChild($child2);
$child1OfChild1 = new File();
$child1OfChild1->setTitle('Child 1 of child 1');
$child1->addChild($child1OfChild1);
$child2OfChild1 = new File();
$child2OfChild1->setTitle('Child 2 of child 1');
$child1->addChild($child2OfChild1);
$parent->tableUpdate(array('drop'=>true));
$parent->save();
$children = $parent->getChildren();
echo '+ '.$parent->getPrimaryKey();
echo ' - '.$parent->getTitle();
echo "\r\n";
while(count($children)){
$child = array_shift($children);
echo ' + '.$child->getPrimaryKey();
echo ' - '.$child->getTitle();
$count = $child->countChildren();
echo ' --> '.(($count>0)?$count.' children':'no child');
echo "\r\n";
}
// + 1 - Root file
// + 2 - Child 1 --> 2 children
// + 5 - Child 2 --> no child
Available methods
The nested set model introduce the following methods:
Method "getParent"
- Description: Return the parent record. Result is cached after its first retrieval but it is possible to force its reloading by setting the 'force' option.
- Param options array not required: May contain the following options
- force bool: Bypass the caching of the parent record.
- Return: Parent record or null if current record is root
Method "getChildren"
- Description: Return the children associated to this record. Records are cached unless the option 'force' is present. The level of depth can be provided with the option 'depth'. If the depth is 1, only the direct descendants are retrieved, if greated than 1, this indicate the number of level in the hierarchy, if equals or less than 0, the number of level is infinite.
- Param options array not required: May contain the following options
- force bool: Force the reloading of children
- depth int: Level of depth to load sub-children
- flatten bool: Return all the record instead of the direct descendants
- Return: Array of records
Method "getRootline"
- Description: Return the parents of the current child. The method only apply to record which have been previously saved (inserted into the rootline) otherwise false is returned.
- Param options array not required: May include all the options present in 'find' method plus:
- exclude_itself bool: Include current child in the rootline
- Return: Array of parent records
Method "isRoot"
- Description: Check wether the current record is the root record.
- Return: Boolean true if records is root record otherwise false
Method "getRoot"
- Description: Return the root record. There is only one root record for a given type of records.
- Return: PorteRecord The root record
Method "addChild"
- Description: Add a child record to the current record.
- Param child PorteRecord required: The record to add as child of the current record.
- Return: PorteRecord The current record
Method "setParent"
- Description: Set a record as the parent of the current record, in other words, move the current record as a child of the provided record.
- Param parent PorteRecord required: The new parent of the current record.
- Return: PorteRecord The current record
Method "countChildren"
- Description: Count the number of children own by this child. By default, it return the number of direct descendants, but this behavior can be altered with the 'depth' option. If 'depth' is zero or negative, all the descendant will be included. If 'depth' is 1, only the direct descendant are included.
- Param options array not required: May contain the following options
- depth int: Level of depth to search for, default 1
- Return: int Number of children
Method "deleteChildren"
- Description: Remove from the database all the children of the current record.
- Return: PorteRecord The current record