Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Generate hierarchy from a many to many relationship

I'm having trouble to generate the hierarchy from the data consumed from an API.

At this moment, there's a many-to-many relationships between two models: Tags and Nodes.

Now, what I need is set a parent_id on the Tag model to know which Tag is its parent. This will be recursive because there are several levels of depth.

The thing is that this process needs to be elaborated from the actual data of the many to many relationships. So I've been playing with the collections (Node::all()/Tag::all()) to try to create this structure, to then mass-assign the ids of the parent Tag in the children tags.

My idea is to load the tags from the Nodes, then create a new item in the collection for every tag child of the node

so this:

|
|__Node A
|  |__Tag 1
|  |__Tag 2
|  |__Tag 3
|
|__Node B
|  |__Tag 1
|  |__Tag 3
|  
|__Node c
   |__Tag 1
   |__Tag 2

Could be converted to this (i know that every item needs to have a unique key, I was thinking assigning one temporary):

|
|__Node A
|  |__Tag 1
|
|__Node A
|  |__Tag 2
|
|__Node A
|  |__Tag 3
|
|__Node B
|  |__Tag 1
|
|__Node B
|  |__Tag 3
|  
|__Node c
|  |__Tag 1
|  
|__Node c
   |__Tag 2

Then I could groupBy (recursively) the tag key resuting into this:

|__Tag 1
   |
   |__Tag 2
   |  |
   |  |__Node A
   |  |__Node C
   |
   |__Tag 3
      |
      |__Node A
      |__Node B

My problem is that, don't know (yet) how to make this transformation properly.

like image 301
Kenny Horna Avatar asked Nov 07 '22 20:11

Kenny Horna


1 Answers

Use a best practice

First of all I suggest you to have a look at this toturial. as a best practice to make hierarchy data by using weights.

Use Eloquent

and also as you use Laravel eloquent relations as it's active record

//in Tag Model
public function children()
{
    return $this->hasMany('App\Models\Tag', 'parent_id');   
}

public function parent(){
     return $this->belongsTo('App\Models\Tag', 'parent_id');
}

public function nodes()
{
    return $this->hasMany('App\Models\Node', 'node_id', 'node_id');   
}

then you can get the result

//there should be a relation for node also 
Tag::with('parent', 'children.children', 'node')->get();

a simple php way

but also Here is a simple way I think:

foreach ($tags as $key => $value) {
    $tagTree[$value['tag_id']] = $value;
    $tagTree[$value['tag_id']]['child'] = array();
}

foreach ($tagTree as $key => $value) {
    if ($value['parent_id'] == 0) {
        $root[$key] = &$tagTree[$key];
    } else {
        $tagTree[$value['parent_id']]['child'][$key] = &$tagTree[$key];
    }

    //here you can check if is there any node for current tag insert 
    //$tagTree[$value['parent_id']]['node'][] = ...
}
like image 162
Saeed.Gh Avatar answered Nov 13 '22 22:11

Saeed.Gh