This type is created by adding parent field into the model, that will store paren’t id of the current record. For root records the value of this field is "-1".

Attention! In Model there can be only one "parent" field.

Sample of standard use of tree when creating a menu of nested pages.

class Pages extends Model
    protected $name = "Pages menu";

    protected $model_elements = array(
        array("Activate", "bool", "active", array("on_create" => true)),
        array("Display in menu ", "bool", "in_menu", array("on_create" => true)),
        array("Name", "char", "name", array("required" => true)),
        array("Parent section", "parent", "parent", array("max_depth" => 3)),
        array("Position", "order", "order"),
        array("Content", "text", "content", array("rich_text" => true))

Linked Tree

To create a structure as "catalog -> catalog -> catalog -> product" or "album -> album -> image " you need to link the model with the “parent ” field of another model in a way so the end parent of the first model will be a foreign key for other model records.

Sample of creating a linked tree for multi-level product catalog.

class Catalogs extends Model 
    protected $name = "Catalog sections";

    protected $model_elements = array(
        array("Active", "bool", "active", array("on_create" => true)),
        array("Name", "char", "name", array("required" => true)),
        array("Catalog", "parent", "parent", array("parent_for" => "Products")),                
        array("Link", "url", "url"),
        array("Position", "order", "order")                    

class Products extends Model 
    protected $name = "Catalog Products";

    protected $model_elements = array(
        array("Active", "bool", "active", array("on_create" => true)),
        array("Name", "char", "name", array("required" => true)),
        array("Catalog section", "enum", "parent", array("foreign_key" => "Catalogs", "is_parent" => true)),
        array("Price", "int", "price", array("required" => true)),
        array("Images", "multi_images","images"),
        array("Description", "text", "desc", array("rich_text" => true)),
        array("Position", "order", "order")

Special Tree Methods

For a quick access to parents and descendants there are ad hoc methods designed in a tree.

  • getParents($id) - returns an array of parent records (till a record with value of a parent field as "-1"). In a result array the keys - are ids of records, values - names of records according to "$name_field" parameter from Model Settings section.
  • getChildren($id) - returns an array of all child records, recursively bypassing all branches of the tree. The resulting array is built similarly by previous method.
  • displayBreadcrumbs($id, $url_first [, $url_field]) - displays a linked path to a record with the passed id. Returns a sequence of HTML tags as "the link-> the link-> the link-> span". Input parameters: an id of the current record, $url_first - the first part of url, optional parameter of $url_field - the name of a field in which the text link for this record is stored (to create an url as "catalog/toys/"). For pre-installed "Pages" model the links are automatically assembled as "/page/4/" and "/contacts/ without the first part).
$catalog = $mv -> catalogs -> findRecordById(43);

//Parent records
$parents = $mv -> catalogs -> getParents($catalog -> id);

//Descendant records
$children = $mv -> catalogs -> getChildren($catalog -> id);

//Link path to catalog section
echo $mv -> catalogs -> displayBreadcrumbs($catalog -> id, "category", "url");

//Link path to catalog product  
echo $mv -> products -> displayBreadcrumbs($product -> id, "category");

//Link path will be like 
<a href="/category/toys/">Toys</a>
<a href="/category/balls/">Ball</a>
<span>Red ball</span>

Above mentioned methods can be called from within a model object. In the sample below we will define a catalog page based on URL.

public function defineCatalogPage(Router $router)
    $url_parts = $router -> getUrlParts();
    $content = false;

    if(count($url_parts) == 2)
            $content = $this -> findRecord(array("id" => $url_parts[1], "active" => 1));
            $content = $this -> findRecord(array("url" => $url_parts[1], "active" => 1));

        $this -> parents = $this -> getParents($content -> id);

    return $content;

Then we are recursively building a catalog menu.

public function displayCatalogMenu($parent)
    $rows = $this -> select(array("parent" => $parent, "active" => 1, "order->asc" => "order"));
    $html = "";
    $root_path = $this -> root_path."category/";

    foreach($rows as $row)
        $active = "";
        $children = false;

        if($row['id'] == $this -> id || array_key_exists($row['id'],  $this -> parents))
            $children = $this -> select(array("parent" => $row['id'], "active" => 1));
            $active = ' class="active"';

        $url = $root_path.($row['url'] ? $row['url'] : $row['id'])."/";
        $html .= '<li><a'.$active.' href="'.$url.'">'.$row['name'].'</a>';

            $html .= "<ul>".$this -> displayCatalogMenu($row['id'])."</ul>";

        $html .= "</li>";        

    return $html;

//Call of this method in the template 
<ul id="catalog">
    <? echo $mv -> catalogs -> displayCatalogMenu(-1); ?>