How to implement a self referencing (parent_id) model in cakephp

三世轮回 提交于 2019-12-31 22:26:19

问题


I have a table called categories. The table holds categories and their sub(subsub)categories...

Its an easy table:

  • id
  • parent_id
  • title

This way I can make categories with endless depth... I kinda hoped that cakephp would understand parent_id (I also tried category_id, but that makes cakePHP join on itself :D )

What is the right way to tackle this?

NOTE: There is also a 'many to many' table called places. Those places can belong to one or more categories.


回答1:


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).




回答2:


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.




回答3:


In Category model: belongsTo Parent and hasMany Children, both have the class 'Category' and foreign key 'parent_id'




回答4:


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;
} 



回答5:


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']);



回答6:


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



来源:https://stackoverflow.com/questions/8070914/how-to-implement-a-self-referencing-parent-id-model-in-cakephp

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!