Laravel 按日期获取历史记录(优化)

Laravel Get previous records by date (optimization)

我有一个预订 table 字段:

我 select 一些预订并将它们显示为列表。我也查下之前的预订是不是相隔不到30天

我通过查询之前预订的每个预订来做到这一点:

@if ($booking->previousBooking()) // Simplified version but you get the idea

底层代码:

public function previousBooking()
    {
        return Booking::where('from', '<', $this->from)
            ->orderByDesc('from')
            ->first();
    }

您可能已经猜到了:它会为每个预订添加一个查询。

最好的方案是预先加载 "previous booking"(带有),以便像这样访问它:

$booking->previous_booking->from

有什么办法可以这样吗?

限制条件:

看看 Jonathan Reinink 的 this article。您可以通过在预订模型上模拟 previous_booking_id 来应用他的解决方案。然后添加 previousBooking() 关系并使用 with('previousBooking') 查询。如果您在实施方面需要任何帮助,请告诉我。

更新


将以下范围添加到您的预订模型中:

public function previousBooking()
{
    return $this->belongsTo(Booking::class);
}

public function scopeWithPreviousBooking($query)
{
    $query->addSelect(['previous_booking_id' => Booking::select('id')
        ->whereColumn('previous_booking.from', '<', 'bookings.to')
        ->orderByDesc('from')
        ->take(1)
    ])->with('previousBooking');
}

您现在可以通过以下方式获取所有包含之前预订 ID 的预订:

$bookings = Booking::withPreviousBooking()->get();

所有预订现在都应该有 previous_booking_id。我们将 with('previousBooking') 添加到范围的末尾,就像我们查询预订关系一样。 Eloquent 不关心 previous_booking_id 是否在数据库中,只要它在模型中可用(我们已通过 addSelect() 方法完成)。

您现在应该能够在您的视图中使用您请求的解决方案:

$booking->previousBooking->from

注意:如果您应用了范围,您只能访问以前的预订关系。如果不是,则 previous_booking_id 不可用,因此关系将为空。如果您总是想加载以前的预订,请考虑将其添加为 global scope。但是,我建议只在需要的地方应用范围。