【发布时间】:2020-09-20 18:49:05
【问题描述】:
我有一个 Laravel 应用程序,其中有一个模型表和一个他们被预订的日期表。只有输入了预订日期的模特才会在日期表中显示日期。日期逐日存储。所以架构看起来如下(简化):
tbl_models
id | name | details | gender
1 | joe bloggs | over 60 | male
2 | jill bloggs | pink nails | female
3 | a n other | greying | male
tbl_ModelCalendar
id | model_id | date
1 | 1 | 2020-06-05 00:00:00
2 | 1 | 2020-06-06 00:00:00
3 | 1 | 2020-06-07 00:00:00
4 | 3 | 2020-09-15 00:00:00
我希望能够根据在特定日期范围内未预订的型号来选择型号。因此,我们输入一个 NotBookedOutFrom 日期对象和一个 NotBookedOutTo 日期对象,并返回这两个日期之间可用的任何模型。我想我需要一个子查询吗?我不能 INNER JOIN 预订表,因为它会忽略任何没有任何预订日期的模型(即一直免费 - 理想!)而且我不能 LEFT JOIN 因为它会返回一个基于在我们省略的日期范围之外的另一个可用日期。
目前,我的控制器中的代码块如下所示:
$model->select('tbl_models.*');
$from = DateTime::createFromFormat('Y-m-d', Carbon::parse($NotBookedOutFrom)->format('Y-m-d'));
$to = DateTime::createFromFormat('Y-m-d', Carbon::parse($NotBookedOutTo)->format('Y-m-d'));
$interval = DateInterval::createFromDateString('1 day');
$period = new DatePeriod($from, $interval, $to);
$model->leftJoin('tbl_ModelCalendar', 'tbl_ModelCalendar.model_id', '=', 'tbl_models.id');
$bookedDates = array();
foreach ($period as $dt) {
$thisDate = $dt->format("Y-m-d H:i:s");
$bookedDates[] = $thisDate;
}
$model->whereNotIn('tbl_ModelCalendar.date', [$bookedDates]);
无论如何,不用说,这不起作用而且是一团糟。我肯定在这里错过了一些非常简单的东西,但我已经转了几个小时了。
编辑:
在 Akina 的建议下,我尝试将他的答案翻译为 Query Builder,但仍不排除已预订的模型:
$model->leftJoin('tbl_ModelCalendar', 'tbl_models.id', '=', DB::raw("tbl_ModelCalendar.model_id AND tbl_ModelCalendar.date BETWEEN $from AND $to"));
$model->whereNull('tbl_ModelCalendar.model_id');
【问题讨论】:
-
在 WhereNotIn 中应用
tbl_ModelCalendar.date的条件后,您的 LeftJoin 将变为 InnerJoin。此条件必须是加入条件的一部分。 -
谢谢@Akina。这是否意味着只删除上面的 leftJoin() ?这仍然无法解决这样一个事实,即如果用户选择 6 月 6 日至 7 日之间可用的模型,它将返回模型 1 的结果,因为它们在 6 月 5 日可用。
-
这是否意味着只删除上面的 leftJoin()? 在实践中,我建议使用纯 SQL 创建正确的查询,然后将其转换为 Laravel 形式。