I have a table called categories. The table holds categories and their sub(subsub)categories...
Its an easy table:
Related question - assume I have a 3 level self-referencing hierarchy implemented as advised by @RichardAtHome - I understand when I try to find a particular Category it will also get me the parent category and all children categories. However how can I make it find the path back to root? Is there some clean trick to accomplish this or will require a custom hack?
I imagine using this in a scenarios where the Product table has one category ID associated with it but when displaying to users I would like to also display the entire parent chain so that they can see something like 'confectionaries/seasonal/nestle' - and then the user can alter the entire product hierarchy
Tree behaviour is overkill for this situation. You just need to set your model up like this:
class Category extends AppModel {
public $hasMany = array(
'Children'=>array(
'className'=>'Category',
'foreignKey'=>'parent_id'
)
);
public $belongsTo = array(
'Parent'=>array(
'className'=>'Category',
'foreignKey'=>'parent_id'
)
);
}
Now, when you do a find() on Category, you'll get two additional Models called Parent (which points to the parent id) and Children (which lists it's children).
In Category model: belongsTo Parent and hasMany Children, both have the class 'Category' and foreign key 'parent_id'
RichardAtHome's answer is the right one. In CakePHP 3.+ you write:
$this->hasMany('Children', [
'className'=>'Category',
'foreignKey'=>'parent_id'
]);
$this->belongsTo('Parent', [
'className'=>'Category',
'foreignKey'=>'parent_id'
]);
and don't forger to use 'contain' in your 'find', e.g.:
$categories = $this->find("all")
->order(...)
->contain(['Children']);
the following custom recursive function tree()
worked for me
public function index() {
$c = $this->tree();
debug($c);
exit;
}
function tree($parent=null){
$arr = array();
$categories = $this->Category->find('all',array(
'conditions'=>array('Category.parent_id '=> $parent)
));
foreach($categories as $key => $category){
$arr[$category['Category']['id']]['title'] = $category['Category']['name'];
$arr[$category["Category"]["id"]]['children'] = $this->tree($category['Category']['id'] );
}
return $arr;
}
Look at the tree behaviour; with MPTT logic. The link supplied to Oracle's website is dead; but you can find a bunch of material about how to use it on the cake manual and online.
CREATE TABLE categories (
id INTEGER(10) UNSIGNED NOT NULL AUTO_INCREMENT,
parent_id INTEGER(10) DEFAULT NULL,
lft INTEGER(10) DEFAULT NULL,
rght INTEGER(10) DEFAULT NULL,
name VARCHAR(255) DEFAULT '',
PRIMARY KEY (id)
);
Just make sure your table matches that structure for best results within Cake and it's baking.