简体   繁体   English

Laravel 5.2 急切负载关系与汇总计算

[英]Laravel 5.2 eager load relation with summary calculation

I am working on a simple tasks app.我正在开发一个简单的任务应用程序。 I want to eager load the total time spent for each project.我想急切加载每个项目花费的总时间。 I have two tables:我有两个表:

Table: task_project 
id, client_id, name, description

Table: task_entries
id, task_project_id, start_time, end_time

The relationship between tables is established via task_project.id = task_entries.task_project_id .表之间的关系通过task_project.id = task_entries.task_project_id建立。

For each project in table task_project , we track time for each task in task_entries .对于表task_project每个项目,我们跟踪task_project中每个任务的task_entries I have created a method called elapsed to handle this.我创建了一个名为elapsed的方法来处理这个问题。

So in my model TaskProject I have a relationship for tasks and for elapsed :所以在我的模型TaskProject我有一个taskselapsed的关系:

public function tasks()
{
    return $this->hasMany(TaskEntry::class, 'task_project_id');
}

public function elapsed()
{
    return $this->hasOne(TaskEntry::class, 'task_project_id')
        ->selectRaw('time_format(SUM(timediff(task_end_time, task_start_time)), "%H:%m:%s") AS hours')
        ->groupBy('task_entries.task_project_id');
}

And then in my controller I call it as follows:然后在我的控制器中我这样称呼它:

$tasks = TaskProject::with('elapsed')->paginate(15);

But the relation for elapsed is a null value for each project row.但是对于每个项目行, elapsed的关系是一个空值。

I would like to end up being able to access this value in my blade template as hh:mm:ss by using:我希望最终能够通过使用以下方式在我的刀片模板中以 hh:mm:ss 的形式访问此值:

$task->elapsed->hours

Any help is appreciated!任何帮助表示赞赏!

Thats an interesting approach.这是一个有趣的方法。 I've faced the problem of how to get a list of aggregates from Eloquent before.我之前遇到过如何从 Eloquent 获取聚合列表的问题。 This is the best I've been able to come up with.这是我能想到的最好的。

class TaskEntry
{
    public static function addElapsedTo($tasks)
    {
        $ids = $tasks->pluck('id');
        $placeholders = trim(str_repeat('?,', count($ids)), ',');

        $times = DB::select('
            SELECT 
                task_project_id,
                TIME_FORMAT(
                    SUM(TIMEDIFF(task_end_time, task_start_time)),
                    "%H:%m:%s"
                ) AS hours
            FROM task_entries
            WHERE task_project_id IN ('.$placeholders.')
            GROUP BY task_project_id
        ', $ids);

        $times = collect($times)->groupBy('task_project_id');

        foreach ($tasks as $task)
        {
            $task->setAttribute('elapsed', $times[$task->task_project_id]['hours']);
        }
        return $tasks;
    }
}

Then you can use it like this.然后你可以像这样使用它。

$tasks = TaskProject::paginate(15);
$tasks = TaskEntry::addElapsedTo($tasks);

$task->elapsed contains the elapsed hours value. $task->elapsed包含经过的小时值。

This way you execute two database queries instead of one.通过这种方式,您可以执行两个数据库查询而不是一个。 But you still avoid executing a query for every result.但是您仍然避免对每个结果执行查询。

Methods like this have worked well for me.像这样的方法对我来说效果很好。 Though it feels a little kludgy.虽然感觉有点鸡肋。 I would love to find a better way.我很想找到更好的方法。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM