7

In CakePHP, how do you select just a subtree in a model which actsAs tree?

I tried this, to find the tree headed by the item with label = "My Label"

$this->find("threaded", array(
    "conditions" => array(
        "label" => "My Label"
    )
));

...however looking at the logs, it runs this SQL:

SELECT Menu.id, Menu.parent_id, Menu.lft, Menu.rght, Menu.label, Menu.link
FROM menus Menu
WHERE label = 'My Label'

Which obviously only selects the one node, and not all its children.

nickf
  • 537,072
  • 198
  • 649
  • 721

1 Answers1

15

It seems you will have to do it in two steps like this (from the manual):

$parent = $this->Category->find('first', array(
    'conditions' => array('label' => 'My label')
));
$parentAndChildren = $this->Category->find('threaded', array(
    'conditions' => array(
        'Category.lft >=' => $parent['Category']['lft'], 
        'Category.rght <=' => $parent['Category']['rght']
    )
));

You can't use the 'label' => 'my label' condition in the threaded call, since it would only find results that match that condition, parents and children. 'threaded' only rearranges the results of a normal find operation based on the parent_id, so you'll have to supply your own condition of what "children" are by using the lft/rght columns.

bancer
  • 7,475
  • 7
  • 39
  • 58
deceze
  • 510,633
  • 85
  • 743
  • 889
  • yeah I ended up doing pretty much exactly this same thing - it seems funny to not have included this functionality in the component. – nickf Oct 21 '09 at 04:57
  • I agree, seems like an obvious use case. There's `->children()` but no `->childrenThreaded()`. Poking around the model class I'm thinking you could probably do `$model->_findThreaded('after', null, $model->children($id))` if you're going by id, but it seems kinda hacky. :o) – deceze Oct 21 '09 at 08:28
  • 1
    Thanks for the answer, I also hoped for a way that is more concise than this. By the way, if you only want the children you should use `'conditions' => array('Category.lft >' => $parent['Category']['lft'], 'Category.rght <' => $parent['Category']['rght'])` to not fetch the parent again. – bfncs Oct 02 '12 at 07:09
  • Hi, how do I display it to my view? How do I loop if I have 10 level of children... – Mico Feb 21 '14 at 05:02