2016-04-23 15 views
1

Ich arbeite an einer einfachen Aufgaben-App. Ich möchte gerne die Gesamtzeit für jedes Projekt aufladen. Ich habe zwei Tabellen:Laravel 5.2 Eager Load Relation mit summarischer Berechnung

Table: task_project 
id, client_id, name, description 

Table: task_entries 
id, task_project_id, start_time, end_time 

Die Beziehung zwischen Tabellen über task_project.id = task_entries.task_project_id hergestellt wird.

Für jedes Projekt in der Tabelle task_project verfolgen wir die Zeit für jede Aufgabe in . Ich habe eine Methode namens elapsed erstellt, um dies zu behandeln.

Also in meinem Modell TaskProject Ich habe eine Beziehung für tasks und für elapsed:

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

Und dann in meinem Controller Ich nenne es wie folgt:

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

Aber das Verhältnis für elapsed ist ein Nullwert für jede Projektreihe

Ich mag diesen Wert in Vorlage meiner Klinge in der Lage, am Ende für den Zugriff als hh: mm: ss durch die Verwendung:

$task->elapsed->hours 

Jede Hilfe ist willkommen!

Antwort

1

Das ist ein interessanter Ansatz. Ich habe das Problem gesehen, wie ich eine Liste von Aggregaten von Eloquent erhalten kann. Das ist das Beste, was ich mir vorstellen konnte.

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

Dann können Sie es so verwenden.

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

$task->elapsed enthält den Wert für verstrichene Stunden.

Auf diese Weise führen Sie zwei Datenbankabfragen statt einer aus. Sie vermeiden jedoch weiterhin die Ausführung einer Abfrage für jedes Ergebnis.

Methoden wie diese haben gut für mich gearbeitet. Obwohl es sich ein wenig klumpig anfühlt. Ich würde gerne einen besseren Weg finden.

+0

Danke @programmerKev! – TheRealPapa

Verwandte Themen