336px-Sorted_binary_tree_inorder.svg

Storing Multiple Trees with the CakePHP TreeBehavior

In order to store multiple trees in the same table you must scope them. The scope is a foreign key. For example, in my app I am storing project schedules in an MPTT tree. Think of a gantt chart.

A Schedule hasMany Tasks and a Task belongsTo a Schedule. Therefore we would scope the Task tree by the foreign key schedule_id. However you cannot define scope in your model like this:

class Task extends AppModel {
    var $name = 'Task';
    var $belongsTo = array('Schedule');
    var $actsAs = array('Tree' => array(
        'scope' => 'schedule_id'
    ));
}

If you dig through the API you’ll see that when scope is used it is added to the SQL query as a condition. Therefore the condition would need to be something more like ‘schedule_id = 3′. Since each tree would be unique you must define the scope when you are working with a specific tree. The solution is to take the actsAs out of your model and attach it on the fly when you are modifying that model’s data. For example:

function add() {
    $this->Task->Behaviors->attach('Tree', array(
        'scope' => "Task.schedule_id = {$this->data['Task']['schedule_id']}"
    ));
    $this->Task->create();
    $this->Task->save($this->data);
}

Illustration by Pluke via Wikipedia was released to the public domain