Родственные отношения родителей и детей на той же модели
У меня есть модель CourseModule
, и каждый из элементов связан с одной и той же моделью.
Структура базы данных:
![введите описание изображения здесь]()
Отношение в модели:
public function parent()
{
return $this->belongsTo('App\CourseModule','parent_id')->where('parent_id',0);
}
public function children()
{
return $this->hasMany('App\CourseModule','parent_id');
}
Я попробовал следующее, но он возвращает только один уровень отношения.
Пробовал:
CourseModule::with('children')->get();
Я пытаюсь создать json-выход, как показано ниже,
Ожидаемый результат:
[
{
"id": "1",
"parent_id": "0",
"course_id": "2",
"name": "Parent",
"description": "first parent",
"order_id": "1",
"created_at": "-0001-11-30 00:00:00",
"updated_at": "-0001-11-30 00:00:00",
"children": [
{
"id": "2",
"parent_id": "1",
"course_id": "2",
"name": "Child 1",
"description": "child of parent",
"order_id": "2",
"created_at": "-0001-11-30 00:00:00",
"updated_at": "-0001-11-30 00:00:00",
"children": [
{
"id": "3",
"parent_id": "2",
"course_id": "2",
"name": "Child2",
"description": "child of child1",
"order_id": "2",
"created_at": "-0001-11-30 00:00:00",
"updated_at": "-0001-11-30 00:00:00",
"children": [
{
"id": "4",
"parent_id": "3",
"course_id": "2",
"name": "Child 3",
"description": "child of child 2",
"order_id": "2",
"created_at": "-0001-11-30 00:00:00",
"updated_at": "-0001-11-30 00:00:00",
"children": []
}
]
}
]
}
]
}
]
Я не понимаю, как получить внутренние дочерние объекты.
Ответы
Ответ 1
Вы должны были бы рекурсивно получить детей, если у вас есть такая неизвестная глубина.
Другой вариант - использовать модель вложенных множеств вместо модели списка смежности. Вы можете использовать что-то вроде baum/baum
для Laravel для вложенных наборов.
"Вложенный набор - это разумный способ реализовать упорядоченное дерево, которое позволяет выполнять быстрые нерекурсивные запросы". - https://github.com/etrepat/baum
С этим пакетом у вас есть методы, такие как getDescendants
чтобы получить все дочерние и вложенные дочерние toHierarchy
и toHierarchy
чтобы получить полную древовидную иерархию.
Википедия - Модель вложенного множества
Baum - шаблон вложенных наборов для Laravel Eloquent ORM
Управление иерархическими данными в MySQL
Ответ 2
Вы должны использовать with('children')
в отношении детей и with('parent')
в родительских отношениях.
Чтобы ваш код был рекурсивным:
public function parent()
{
return $this->belongsTo('App\CourseModule','parent_id')->where('parent_id',0)->with('parent');
}
public function children()
{
return $this->hasMany('App\CourseModule','parent_id')->with('children');
}
Примечание. Убедитесь, что в вашем коде есть те или иные условия выхода, иначе он окажется в бесконечном цикле.
Ответ 3
здесь - это ответ, который может помочь вам
Думаю, вам нужно сделать это рекурсивно, чтобы получить цельное дерево:
$data = CourseModule::with('child_rec');
Рекурсивная функция
Это может помочь вам в соответствии с вашим требованием,
public function child()
{
return $this->hasMany('App\CourseModule', 'parent');
}
public function children_rec()
{
return $this->child()->with('children_rec');
// which is equivalent to:
// return $this->hasMany('App\CourseModule', 'parent')->with('children_rec);
}
// parent
public function parent()
{
return $this->belongsTo('App\CourseModule','parent');
}
// all ascendants
public function parent_rec()
{
return $this->parent()->with('parent_rec');
}
Ответ 4
Вы всегда можете создать свою собственную рекурсивную функцию, в моем случае я делаю это как следующий код.
<?php
declare(strict_types=1);
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Akmeh\Uuid;
/**
* Class Location
* @package Domain\Models
*/
class Location extends Model
{
use Uuid;
/**
* Indicates if the IDs are auto-incrementing.
*
* @var bool
*/
public $incrementing = false;
public $timestamps = false;
/**
* @param string $id
* @param array $tree
* @return array
*/
public static function getTree(string $id, array $tree = []): array
{
$lowestLevel = Location::where('id', $id)->first();
if (!$lowestLevel) {
return $tree;
}
$tree[] = $lowestLevel->toArray();
if ($lowestLevel->parent_id !== 0) {
$tree = Location::getTree($lowestLevel->parent_id, $tree);
}
return $tree;
}
}
Ответ 5
Функция модели:
public function Children()
{
return $this->hasMany(self::class, 'Parent', 'Id')->with('Children');
}
Функция контроллера:
Menu::with("Children")->where(["Parent" => 0])->get();
Ответ 6
это должно нравиться вашим модельным отношениям
// parent relation
public function parent(){
return $this->belongsTo(self::class , 'parent_id');
}
//child relation
public function children()
{
return $this->hasMany(self::class ,'parent_id');
}
public function ascendings()
{
$ascendings = collect();
$user = $this;
while($user->parent) {
$ascendings->push($user->parent);
if ($user->parent) {
$user = $user->parent;
}
}
return $ascendings;
}
public function descendings()
{
$descendings = collect();
$children = $this->children;
while ($children->count()) {
$child = $children->shift();
$descendings->push($child);
$children = $children->merge($child->children);
}
return $descendings;
}