首页 > 解决方案 > 如何使用 laravel 8 获取 mysql 记录 created_at 时间戳之间的持续时间

问题描述

我想知道一个事件持续了多长时间,而不必为该事件添加完成时间。

为了演示,我创建了一个简单的练习:

事件表:

Schema::create('events', function (Blueprint $table) {
    $table->id();
    $table->string('name');
    $table->timestamps();
});

INSERT INTO `events` (`id`, `name`, `created_at`, `updated_at`) VALUES
(1, 'Event 1', '2021-08-19 10:41:16', '2021-08-19 10:41:16'),
(2, 'Event 2', '2021-08-19 11:11:25', '2021-08-19 11:11:25'),
(3, 'Event 3', '2021-08-19 11:25:21', '2021-08-19 11:25:21'),
(4, 'Event 4', '2021-08-19 11:35:28', '2021-08-19 11:35:28'),
(5, 'Event 5', '2021-08-19 11:45:38', '2021-08-19 11:45:38');

我目前正在从数据库中提取数据:

public function index()
{   
    return Event::get();
}

它返回以下内容:

{
    id: 1,
    name: "Event 1",
    created_at: "2021-08-19T10:41:16.000000Z",
    updated_at: "2021-08-19T10:41:16.000000Z"
},
{
    id: 2,
    name: "Event 2",
    created_at: "2021-08-19T11:11:25.000000Z",
    updated_at: "2021-08-19T11:11:25.000000Z"
},
{
    id: 3,
    name: "Event 3",
    created_at: "2021-08-19T11:25:21.000000Z",
    updated_at: "2021-08-19T11:25:21.000000Z"
},
{
    id: 4,
    name: "Event 4",
    created_at: "2021-08-19T11:35:28.000000Z",
    updated_at: "2021-08-19T11:35:28.000000Z"
},
{
    id: 5,
    name: "Event 5",
    created_at: "2021-08-19T11:45:38.000000Z",
    updated_at: "2021-08-19T11:45:38.000000Z"
}

我想取下一个事件的开始时间并将其用作结束时间来计算持续时间,如果没有下一个事件,则假定事件仍在运行,因此应使用当前时间计算持续时间。

假设我在 13:00 运行查询,我希望得到以下结果(持续时间以秒为单位计算):

[
    {
    id: 1,
    name: "Event 1",
    created_at: "2021-08-19T10:41:16.000000Z",
    updated_at: "2021-08-19T10:41:16.000000Z",
    duration:   "1809"
    },
    {
    id: 2,
    name: "Event 2",
    created_at: "2021-08-19T11:11:25.000000Z",
    updated_at: "2021-08-19T11:11:25.000000Z",
    duration:   "836"
    },
    {
    id: 3,
    name: "Event 3",
    created_at: "2021-08-19T11:25:21.000000Z",
    updated_at: "2021-08-19T11:25:21.000000Z",
    duration:   "607"
    },
    {
    id: 4,
    name: "Event 4",
    created_at: "2021-08-19T11:35:28.000000Z",
    updated_at: "2021-08-19T11:35:28.000000Z",
    duration:   "610"
    },
    {
    id: 5,
    name: "Event 5",
    created_at: "2021-08-19T11:45:38.000000Z",
    updated_at: "2021-08-19T11:45:38.000000Z",
    duration:   "4462"
    }
]

关于如何实现这一目标的任何建议?是否可以通过 eloquent 来实现,或者使用集合之类的东西并计算从数据库中提取数据后的持续时间会更好吗?

标签: phpmysqllaraveleloquent

解决方案


您可以Collection::map()结合使用Carbon::diffInMinutes()(或者您想要区分):

public function index()
{   
    return Event::get()->map(function($event, $key) use($events) {
        $event->duration = 0;
        if ($key < $events->count() - 1) {
            $event->duration = $events[$key + 1]->created_at->diffInMinutes($event->created_at);
        }
        return $event;
    }));
}

如果您不喜欢在控制器中执行此操作,则可以直接在集合中执行此操作:

  1. 通过创建一个新集合php artisan make:collection \\App\\Collections\\EventCollection
  2. 请执行下列操作:
<?php

namespace App\Collections;

use DatePeriod;
use Illuminate\Database\Eloquent\Collection;
 
class EventCollection extends Collection
{
    public function withDuration()
    {
        return $this->map(function($event, $key) {
            $event->duration = 0;
            if ($key < $this->count() - 1) {
                $event->duration = $this[$key + 1]->created_at->diffInMinutes($event->created_at);
            }
            return $event;
        });
    }
}
  1. 在您的Event模型中添加以下内容:
public function newCollection(array $models = [])
{   
    return new EventCollection($models);
}
  1. 像这样使用它:
public function index()
{   
    return Event::get()->withDuration();
}

推荐阅读