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

后端 未结 6 1052
悲&欢浪女
悲&欢浪女 2021-02-06 06:35

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

Its an easy table:

  • id
  • parent_id
  • title
相关标签:
6条回答
  • 2021-02-06 06:46

    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

    0 讨论(0)
  • 2021-02-06 06:49

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

    0 讨论(0)
  • 2021-02-06 06:56

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

    0 讨论(0)
  • 2021-02-06 07:01

    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']);
    
    0 讨论(0)
  • 2021-02-06 07:04

    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;
    } 
    
    0 讨论(0)
  • 2021-02-06 07:06

    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.

    0 讨论(0)
提交回复
热议问题