My CakePHP Category Tree Helper

Hey everyone. Not so much a tutorial here, but more so a snippet of code to help some of you out. My problem was with the CakePHP tree component. The way that the tree organised data in CakePHP works is through establishing a neighbour like system, where the elements are located through analysing not only the parent and children relationships but through where each element is located according to its neighbour. The problem i found with this when it comes to categories is that CakePHP does not seem to have a way to ignore this left and right neighbour checks, and in turn order the data.
So after asking around a bit i decided to write my own method of ordering my tree data in the database, which was a Category list to be used in a select box. My helper came out to be:
/app/views/helpers/tree.php

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
<?php
 
class TreeHelper extends AppHelper {
 
function indentTree($array, $counter=0){
$ret = '';
$array2 = array();
$pre = '';
for($i = 1;$i < $counter; $i++){
$pre .= '--';
}
 
foreach($array as $key => $value){
if($key == 'children'){
if(isset($value['Category']) || (isset($value['children']) && sizeof($value['children']) > 0)){
$indented[] = $this->indentTree($value, ++$counter);
} else {
if(sizeof($value) > 0) {
$indented[] = $this->indentTree($value, $counter);
}
}
} elseif($key == 'Category'){
$indented[$value['id']] = ' '.$pre.' '.$value['name'];
} elseif(isset($value['Category']['name'])){
$indented[] = $this->indentTree($value, $counter);
}
}
return $this->flatten_array($indented, 2);
}
 
function flatten_array($array, $preserve_keys = 0, &$out = array()) {
foreach($array as $key => $child){
if(is_array($child)){
$out = $this->flatten_array($child, $preserve_keys, $out);
} elseif($preserve_keys + is_string($key) > 1){
$out[$key] = $child;
} else {
$out[] = $child;
}
}
return $out;
}
 
}
 
?>

To use this simply include the helper in your controller via:

1
var $helpers = array('Html', 'Form', 'Text', 'Javascript', 'Tree');

And then within your action you must select the data in a threaded form, the same as GenerateTreeList would do, however pre-ordered:

1
2
$categories = $this->Category->find('threaded', array('order' => array('Category.name' => 'ASC')));
$this->set('categoriesList', $categories);

Next up you use the helper in your view via:

1
echo $form->input('parent_id', array('type'=>'select', 'options'=>$tree->indentTree($categoriesList), 'empty'=>'--------', 'div'=>'row'));

And thats it!
For me this will return an ordered flattened array of my categories to be used within the select box!
I know this explanation is a bit low but it should be enough to get you started! If you have any questions please comment and i will see what i can do to help you out!