2017-11-24 13 views
3

私は2つのdatetimesの違いを計算しようとしています。 tasksが多くtask_interactionsがあり、task_interactionstasksに属し:Laravel Carbon - データベースエントリ間の時間を計算する

私は2つのモデル、taskstask_interactionsを持っているが、それらは次のように関連しています。

ユーザーは、タスクのステータスを「進行中」、「一時停止中」、「終了済み」のいずれかに変更できます。ユーザーは「進行中」と「一時停止中」の間でステータスを何度か変更しますが、終了するとタスクのステータスをもう変更できなくなります。

すべての相互作用は、をuser_id、created_atをdatetimeとしてtask_interactionsテーブルに保存されます。テーブルのカラムはid ; task_id ; status ; comments ; created_by ; created_atです。ここで

= 1タスクIDのexempleのNA:私は一つのタスクに費やした時間の合計を持っている事は、ある

# id, task_id, status, comments, created_by, created_at 
144, 1, In Progress, , 1, 2017-11-14 09:42:20 
145, 1, Paused, , 1, 2017-11-14 09:45:53 
146, 1, In Progress, , 1, 2017-11-14 09:46:57 
147, 1, Paused, , 1, 2017-11-14 09:49:57 
148, 1, In Progress, , 1, 2017-11-14 10:00:10 
149, 1, Paused, , 1, 2017-11-14 10:06:25 
150, 1, In Progress, , 1, 2017-11-14 10:07:26 
151, 1, Paused, , 1, 2017-11-14 10:08:11 
153, 1, Paused, , 1, 2017-11-14 11:27:04 
154, 1, In Progress, , 1, 2017-11-14 11:27:21 
155, 1, Paused, , 1, 2017-11-14 11:57:38 

、私はIn ProgressPaused間の時間を決定する必要があります。 PausedIn Progressの間の時間は関係ありません。

私はこれに驚いています。私を助けることができる人はいますか?

ありがとうございます。

私の質問がちょっとダミーに聞こえる場合は、私は非常に経験していないので、ご容赦ください。@foreach task_id = Xのどこでもループしてください。

尋ねたとして、ここで私は、ビューのために渡していたデータです:

public function mytasks() 
    { 
     $users = User::all(); 
     $mytasks = Task::where('assigned_to','=', Auth::id())->where('status','!=','Finished')->get(); 
     $mytaskscount = Task::where('assigned_to','=', Auth::id())->count(); 
     $tasksinprogress = Task::where('status','=','In Progress')->where('assigned_to','=', Auth::id())->get(); 
     $tasksinprogresscount = Task::where('status','=','In Progress')->where('assigned_to','=', Auth::id())->count(); 
     $taskspaused = Task::where('status','=','Paused')->where('assigned_to','=', Auth::id())->get(); 
     $taskspausedcount = Task::where('status','=','Paused')->where('assigned_to','=', Auth::id())->count(); 
     $tasksfinished = Task::where('status','=','Finished')->where('assigned_to','=', Auth::id())->get(); 
     $tasksfinishedcount = Task::where('status','=','Finished')->where('assigned_to','=', Auth::id())->count(); 
     $tasktypes = Tasktype::all(); 
     $chapters = Chapter::all(); 

     return view('pages.tasks_my', compact('mytasks','tasktypes','chapters','tasksinprogress','taskspaused','tasksfinished','mytaskscount','tasksinprogresscount','taskspausedcount','tasksfinishedcount')); 
    } 

そしてもう一つ、私がこれまで知っている

@foreach ($tasks as $task) 
    @foreach ($task->interactions as $interactions) 
{{ In here, every time my loop returns a status = "In progress" i should mark that time, and if that the next loop returns a "Paused", i should count the difference between these two. And sum all other equal cases in the loop. }} 
    @endforeach 
@endforeach 

を私は本当に行う方法については考えているが、その

+0

コントローラを押し込むことはできますか? –

+0

私はこの質問への答えを知りたいと思います – lewis4u

+0

これを処理するためにdbクエリを担当させていただいていますか? PHPで結果を反復することは、何を思い浮かべるかです。 – Chay22

答えて

1

これは厳密なMysqlですが、そのトリックを行う必要があります。 これはraw SQL命令を使って直接laravelで呼び出すことができます。あるいは、これをLaravelコードに書き直してください。

select SEC_TO_TIME(
    sum( 
     timediff(
      if(task_end.created_at is null, 
       NOW(), 
       task_end.created_at), 
      task_start.created_at))) 
from task_interactions task_start 
left join task_interactions task_end 
    ON task_end.task_id = task_start.task_id 
    AND task_end.status IN ('Pause', 'Finished') 
    AND task_end.created_at = (
     SELECT min(created_at) 
     FROM task_interactions 
     WHERE status = task_end.status 
     AND created_at >= task_start.created_at 
    ) 
WHERE task_start.task_id = 1 
AND task_start.status = 'In Progress' 
+0

これが私がLaravelを愛する主な理由です... PHPとSQLのバニラコードはとても醜いですし、読みにくいです... Laravel Eloquentに翻訳するには時間がかかりそうですね – lewis4u

+0

それから読むのが難しいですか? これは基本的なSQLです... あなたはすべてのtask_interactionsを 'In Progress'ステータスにします。私はそれらをtask_startと呼んだ。私は同じtask_id(と私は別名そのtask_end)で他のタスクへの左の結合を行います。その参加のために、私は一時停止または終了したタスクのみが必要です。さらに、私はその目的のために最初の仕事が欲しい... Laravelは良いですが、Eloquentを使ってこれをしたいのなら、まだ複雑です。 Laravelは素晴らしいツールですが、あなたはまだ何をやっているのかを知る必要があります... –

+0

これはコードがあまりにも多いので、laravelと少ないコードで行うことができます! – lewis4u

0

私はDavid's answerをお勧めします。あなたがMySQLを使用して快適にやっていない場合。これはあなたの作業だったときに秒差の合計を与えるべき

$start = Carbon::parse($startTask->created_at); 
$pause = Carbon::parse($endTask->created_at); 

$diffInSeconds = $pause->diffInSeconds($start) 

:それは一時停止されたときにタスクが&開始された最初の時間の間

計算違い:あなたはこのようにそれをしなければならないことがあり開始された&一時停止。今度は、この方法を繰り返して、タスクが再び開始されたときに、&を一時停止する必要があります。

+0

これは少し奇妙に聞こえるかもしれませんが、私はあなたのアプローチを理解していますが、これをforeachループの中に入れる方法はわかりません。私は経験が足りません。いつも私はコントローラーで必要なデータをフィルタリングし、その情報を私の視点で処理します。私は間違っていることを知っています –

+0

これは非常に簡単なので、タスクのすべての一時停止した開始エントリを配列として取得する必要があります。次に、タスクの開始エントリを単純に解析します。 –

+0

私はそれを試してみましょう。どうもありがとう –