在同一模型上雄辩的亲子关系

时间:2016-01-13 05:23:08

标签: php laravel laravel-5 eloquent laravel-5.1

我有一个模型CourseModule,每个项目都与同一模型相关。

数据库结构:

enter image description here

模型中的关系:

    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": []
              }
            ]
          }
        ]
      }
    ]
  }
]

我不明白如何获取内部子对象。

6 个答案:

答案 0 :(得分:11)

您应该在子关系中使用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');
}

注意:确保您的代码有一些或其他退出条件,否则它将以永无止境的循环结束。

答案 1 :(得分:7)

如果您有这样的未知深度,则必须以递归方式获取孩子。

另一种选择是使用嵌套集模型而不是邻接列表模型。对于嵌套集,您可以使用类似baum/baum包的Laravel。

  

"嵌套集是实现有序树的智能方法,允许快速,非递归查询。" - https://github.com/etrepat/baum

使用此程序包,您可以使用getDescendants等方法来获取所有子项和嵌套子项,并使用toHierarchy来获取完整的树层次结构。

Wikipedia - Nested Set Model

Baum - Nested Set pattern for Laravel's Eloquent ORM

Managing Hierarchical Data in MySQL

答案 2 :(得分:4)

here是可以帮助您的答案

我认为你必须递归地检索整棵树:

$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');
}

答案 3 :(得分:2)

你总是可以创建自己的递归函数,在我的例子中我做的代码如下。

use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request;
use Tyre\TyreBundle\Repository\DoctrineProductRepository;
use Tyre\TyreBundle\Repository\ProductRepositoryInterface;


class DefaultController extends Controller
{
    public function indexAction()
    {
        return $this->render('TyreTyreBundle:Default:search.html.twig');
    }
    public function searchAction(Request $request) {

        $repositoryMap = [
            'db' => DoctrineProductRepository::class,
        ];
        $serviceName = $repositoryMap[$request->get('db')]; /***This is Line 56 ***/
        /** @var ProductRepositoryInterface */
        $repository = $this->get($serviceName);
        $results = $repository->search($request->get('search_for'));
        return $this->render('TyreTyreBundle:Default:detail.html.twig', array('results' => $results));

    }

    public function detailAction()
    {
        //forward the user to the search page when he tries to access directly to the detail page
        return $this->render('TyreTyreBundle:Default:search.html.twig');
    }
}

答案 4 :(得分:1)

模型功能:

public function Children()
{ 
    return $this->hasMany(self::class, 'Parent', 'Id')->with('Children');
} 

控制器功能:

Menu::with("Children")->where(["Parent" => 0])->get(); 

答案 5 :(得分:0)

您的模型关系应该是这样

     // 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;
    }