Laravel Orm from Self Referencing Table Get N Level Hierarchy JSON

Laravel ORM from self referencing table get N level hierarchy JSON

Here's how you manually retrieve nested relations:

$collection = Model::with('relation1.relation2.relation3')->get();

So in your case it would be:

$surveys = Survey::with('children.children.children')->get();

Obviously this will do the job when the relations are fixed, but it's not the way to go for a recursive relation to the same table.

Fortunately, you can make such relation recursive, then all you need to retrieve whole tree is this:

$surveys = Survey::with('childrenRecursive');

However, I wouldn't load parent for each row this way.

So here's all you need:

// Survey model
// loads only direct children - 1 level
public function children()
{
return $this->hasMany('Survey', 'parent');
}

// recursive, loads all descendants
public function childrenRecursive()
{
return $this->children()->with('childrenRecursive');
// which is equivalent to:
// return $this->hasMany('Survey', 'parent')->with('childrenRecursive);
}

// parent
public function parent()
{
return $this->belongsTo('Survey','parent');
}

// all ascendants
public function parentRecursive()
{
return $this->parent()->with('parentRecursive');
}

EDIT: To get real tree structure, first query must be limited to only root nodes:

$surveys = Survey::with('childrenRecursive')->whereNull('parent')->get();

Recursive Eloquent Models

Research led me to this thread that suggested how to get recursive records via hasMany

thus

public function replys()
{
return $this->hasMany(Message::class, 'reply_to', 'id');
}

public function replies()
{
return $this->replys()->with('replies');
}

Did not think it would be this easy however, I was hoping that I could have kept it simple without having to devise a complex raw query statement.

My question now is how does this recursive method stand up to large data sets?

I am creating category model where it has parent of category model itself

Some of your categories don't have a parent, they are root nodes, so you must check it $category->parent first, then access its properties.

Now, don't use isset since relation is not set as a property on the object. Use this instead:

if (count($category->parent)) // do something

// or is_null
if (is_null($category->parent));

Also get() returns collection, what you want is first() that returns single model.

I suggest you read this answer about recursive relations to make working with your setup easier:
Laravel ORM from self referencing table get N level hierarchy JSON

And also this one, so you know why I suggest count instead of is_null to check related model:
Laravel check if related model exists

How to display parent child flat table records as nested list in Php?

You can create a self-referring relationship

class Task extends Model{

public function tasks()
{
return $this->hasMany('App\Task', 'parent');
}
}

in your controller:

$tasks = Task::where('parent',0)->get();
return view ('tasks.index',compact('tasks'));

Then make the view recursive.

<div>
@foreach($tasks as $task)
{{$task->name}}
@if(count($task->tasks))
@include('tasks.index',['tasks' => $task->tasks])
@endif
@endforeach
</div>

(might need some cleaning up to prevent confusing the variable names, but you get the general idea)

Eloquent Parent-Child relationship on same model

You would have to recursively get the children if you have an unknown depth like that.

Another option is to use the nested sets model instead of the adjacency list model. You can use something like baum/baum package for Laravel for nested sets.

"A nested set is a smart way to implement an ordered tree that allows for fast, non-recursive queries." - https://github.com/etrepat/baum

With this package you have methods like getDescendants to get all children and nested children and toHierarchy to get a complete tree hierarchy.

Wikipedia - Nested Set Model

Baum - Nested Set pattern for Laravel's Eloquent ORM

Managing Hierarchical Data in MySQL



Related Topics



Leave a reply



Submit