【问题标题】:Sort collection by relationship value按关系值对集合进行排序
【发布时间】:2017-05-02 13:38:31
【问题描述】:

我想按嵌套关系的属性对 laravel 集合进行排序。

所以我查询了所有项目(只有项目有与当前用户相关的任务),然后我想按任务关系的截止日期对项目进行排序。

当前代码:

项目.php

public function tasks()
{
    return $this->hasMany('App\Models\ProjectTask');
}

任务.php

public function project()
{
    return $this->belongsTo('App\Models\Project');
}

用户控制器

$projects = Project->whereHas('tasks', function($query){
        $query->where('user_id', Auth::user()->id);
    })->get()->sortBy(function($project){
        return $project->tasks()->orderby('deadline')->first(); 
    });

我不知道我是否朝着正确的方向前进? 任何建议表示赞赏!

【问题讨论】:

    标签: laravel eloquent nested


    【解决方案1】:

    使用. 运算符是一种很好的简洁方式

    $projects = Project::all()->load('tasks')->sortBy('tasks.deadline');
    

    【讨论】:

    • 我也尝试过这种方法,但我只想获得分配给我的项目 whereHas 任务,所以我必须使用 whereHas 而我无法获得它使用负载..如果您有更多输入,请告诉我 thnx
    • 所以 load() 不是急切加载?这就像在做一个“JOIN”?
    • 嗨@Mtxz,你是对的load() 是急切加载。 Laravel 不一定要执行明确的JOIN,而是执行一系列受您分配给每个模型的关系约束的查询。我建议您使用 Barry Heuvel 的调试栏 (github.com/barryvdh/laravel-debugbar) 观看您急切加载的结果,因为这比我的解释更能让您了解正在发生的事情
    【解决方案2】:

    我认为您需要使用 join() 之类的东西,然后按您需要的任何内容进行排序。

    例如:

    Project::join('tasks', 'tasks.project_id', '=', 'projects.id')
            ->select('projects.*', DB::raw("MAX(tasks.deadline) as deadline_date"))
            ->groupBy('tasks.project_id')
            ->orderBy('deadline_date')
            ->get()
    

    更新

    Project::join('tasks', function ($join) {
                $join->on('tasks.project_id', '=', 'projects.id')
                    ->where('tasks.user_id', Auth::user()->id)
                    ->whereNull('tasks.completed');
            })
            ->select('projects.*', DB::raw("MAX(tasks.deadline) as deadline_date"))
            ->groupBy('tasks.project_id')
            ->orderBy('deadline_date')
            ->get()
    

    更新2

    在您的查询中添加with:

    ->with(['tasks' => function ($q) {
        $q->where('user_id', Auth::user()->id)
           ->whereNull('completed');
    })
    

    【讨论】:

    • 我认为这将是目前最好的解决方案,但有一个棘手的部分(对我来说),我想按任务的截止日期排序,但只有完成的任务列为空。我尝试添加 whereNull('tasks.completed') 但这不会影响订单。你能在这方面提升一下吗?
    • 完美,现在的顺序是正确的,但我现在仍然在项目数组中缺少我的项目,你能帮我把所有的任务都附加到连接任务表上的 user_id 是特定用户(经过身份验证的用户),您可以看到我在 mij OP 中使用了 whereHas 吗?
    • 只需在您的join 闭包中再添加一个where,查看更新后的答案。
    • 是的,我自己已经添加了一个,但这仍然返回一组平面项目,而我想在每个项目对象中包含任务..
    • 如果您想加载关系,那么with 是您的朋友,请查看更新后的答案。
    【解决方案3】:

    试试这个,

    $tasks = Task::with('project')
                ->where('user_id',Auth::user()->id)
                ->orderBy('deadline')
                ->get();
    

    之后,您可以访问如下项目属性

    $tasks->first()->project()->xxx
    

    【讨论】:

    • 我已经尝试了一些东西,但我希望按项目对任务进行分组。我尝试了 groupby,但由于某种原因我丢失了我的收藏结果。我将尝试加入现在的选项,也许我稍后再试..
    猜你喜欢
    • 2021-03-08
    • 1970-01-01
    • 2022-06-28
    • 2021-01-15
    • 2018-11-20
    • 2015-10-18
    • 2023-03-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多