Метод хорош в случаях, когда в приложении предусматриваются иерархии данных, например жанр->субжанр->субсубжанр и т.д или отдел->секция.
Связь будет организовываться посредством связи полей id -> parent_id. Естественно, эти поля должны быть созданыв базе.
Модель 1
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
class Tag extends Model
{
/**
* Получение родительского тега
*
* @return BelongsTo
*/
public function parent(): BelongsTo
{
return $this->belongsTo(__CLASS__, 'parent_id');
}
/**
* Получение дочерних тегов
*
* @return HasMany
*/
public function children(): HasMany
{
return $this->hasMany(__CLASS__, 'parent_id', 'id') ;
}
/**
* Получение неограниченной вложенности дочерних тегов
*
* @return HasMany
*/
public function childrenAll(): HasMany
{
return $this->hasMany(__CLASS__, 'parent_id', 'id')->with('children');
}
}
Теперь можно получать либо всех непосредственных потомков либо все дерево.
<?php
$resource = Tag::find(3);
$children = $resource->children();
$childrenAll = $resource->childrenAll();
Далее, можно сделать метод, который будет формировать древовидный массив.
public function tree(Tag $tag): array
{
if ($tag->childrenAll) {
$item = [
'id' => $tag->id,
'name' => $tag->name,
'slug' => $tag->slug,
'content' => $tag->content,
'parent_id' => $tag->parent_id
];
foreach ($tag->childrenAll as $value) {
$item['children'][] = $this->tree($value);
}
return $item;
}
return [
'id' => $tag->id,
'name' => $tag->name,
'slug' => $tag->slug,
'content' => $tag->content,
'parent_id' => $tag->parent_id
];
}
Использовать этот метод можно в слое ресурсов или в контроллере. Или еще где-то.
Есть еще альтернативный вариант подобной схемы.
Модель 2
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\HasMany;
class Tag extends Model
{
/**
* Получение дочерних тегов
*
* @return HasMany
*/
public function children(): HasMany
{
return $this->hasMany(__CLASS__, 'parent_id', 'id') ;
}
/**
* Получение неограниченной вложенности дочерних тегов
*
* @return HasMany
*/
public function childrenAll(): HasMany
{
return $this->children()->with('childrenAll');
}
}