首页 > 解决方案 > Laravel 使用查询构建器从日期范围创建行

问题描述

我有一个Event模型,它有EventDates

EventDate有一个fromto字段。在我的仪表板中,如果一个事件跨越多天,我需要使用查询构建器为该事件存在的每一天显示一行,以便我们可以对结果集进行分页和限制。

事件.php

public function dates()
{
    return $this->hasMany(EventDate::class);
}

这就是数据在 EventDate 中的存储方式

+----+------------+------------+
| id |    from    |     to     |
+----+------------+------------+
|  1 | 09-20-2019 | 09-25-2019 |
+----+------------+------------+

这就是我希望接收数据的方式


+----+------------+
| id |    date    |
+----+------------+
|  1 | 09-20-2019 |
|  1 | 09-21-2019 |
|  1 | 09-22-2019 |
|  1 | 09-23-2019 |
|  1 | 09-24-2019 |
|  1 | 09-25-2019 |
+----+------------+

从集合中检索的方法

我可以使用此方法从集合中构建结果,但是这已经是结果的派生者,因此我无法对此进行分页或限制。

事件日期.php

public function getRecurringAttribute()
{
    $dates = collect();
    $this->upcoming()->get()->map(function ($upcomingDate) use ($dates) {
        $period = CarbonPeriod::create($upcomingDate->date_from, $upcomingDate->date_until);
        if (!$period->count()) {
            return $upcomingDate;
        }
        foreach ($period as $date) {
            $upcomingDate->date_from = $date;
            $upcomingDate->date_until = $date;
            $dates->push($upcomingDate);
        }
        return true;
    });

    return $dates;
}

所以我想知道,是否有可能使用查询生成器来实现这个结果?所以我可以对生成的结果集进行分页、限制和使用范围。

标签: phpmysqldatabaselaravel

解决方案


我使用以下库 https://github.com/staudenmeir/laravel-cte/找到了解决方案。该库允许使用查询生成器或模型编写 CTE 函数。

public function scopeRecurringDates($query)
{
    return $query->from('t')
        ->withRecursiveExpression('t', "
            SELECT id, event_id, date_from as date_from, date_from as date_until, date_until as du, time_from, time_until FROM event_dates
            UNION ALL
            SELECT id, event_id, DATE_ADD(t.date_from, INTERVAL 1 DAY), DATE_ADD(t.date_from, INTERVAL 1 DAY), du, time_from, time_until
            FROM t WHERE DATE_ADD(date_from, INTERVAL 1 DAY) <= du
        ");
}

在我的控制器中,我使用

$query = EventDate::recurringDates()

推荐阅读