【问题标题】:Laravel Query: get models where child's date ranges is not in array of date rangesLaravel Query:获取孩子的日期范围不在日期范围数组中的模型
【发布时间】:2018-12-18 09:34:01
【问题描述】:

我有 Event 模型 hasMany childs Time 模型。 Time 是具有 start_timeend_time 字段的日期时间范围。

如何获取所有Events,其中没有孩子Times 与日期范围的array 交叉?

例子:

$events = Event::notInDateRange([
    [ 'start_date' => '2000.01.01 00:00:00', 'end_date' => '2000.01.01 12:00:00' ],
    [ 'start_date' => '2000.01.02 12:00:00', 'end_date' => '2000.01.02 16:00:00' ],
    [ 'start_date' => '2000.01.03 10:00:00', 'end_date' => '2000.01.03 12:30:00' ],
])->get();
// In this case I don't want to get Event where one of Time is 
// [ 'start_date' => '2000.01.03 12:00:00' => 'end_date' => '2000.01.03 14:00:00' ]

【问题讨论】:

标签: laravel laravel-5.7


【解决方案1】:

您可以创建一个新的query scope 以在您的Event 模型中创建一个notInDateRange 范围,并在新范围内使用whereNotBetween where clause

在您的 Event 模型类中,定义一个名为 scopeNotInDateRange 的新函数,该函数接受开始和结束日期并将其定义如下:

public function scopeNotInDateRange($query, $start_date, $end_date)
    $start = new Carbon($start_date);
    $end = new Carbon($end_date);
    return $query->whereNotBetween('start_date', [$start, $end])
                 ->whereNotBetween('end_date', [$start, $end]);

还记得将use Carbon\Carbon; 添加到Event 类的顶部。我们将使用 Carbon 将字符串转换为日期。

然后您可以使用新的查询范围,例如App\Event::notInDateRange($start, $end)。您还可以链接范围,因此在您的示例中您可以使用:

$events = Event::notInDateRange('2000-01-01 00:00:00', '2000-01-01 12:00:00')
               ->notInDateRange('2000-01-02 12:00:00', '2000-01-02 16:00:00')
               ->notInDateRange('2000-01-03 10:00:00', '2000-01-03 12:30:00')
               ->get();

请注意,我还将您在日期中使用的 . 更改为 -,以便 Carbon 能够将字符串转换为日期。

如果您还没有,还请确保当您在 Laravel 中使用访问它们的值时,使用 Date Mutators 将您的 start_dateend_date 列转换为碳日期。为此,请将以下 sn-p 添加到您的 Event 模型类中:

/**
 * The attributes that should be mutated to dates.
 *
 * @var array
 */
protected $dates = [
    'start_date', 'end_date'
];

【讨论】:

  • 感谢您的回答!但是您错过了 Event 模型没有任何时间字段的事情。 Event hasMany childs models Time 其中有start_timeend_time
  • 在这种情况下你可以使用whereDoesntHave,比如$events = App\Event::whereDoesntHave('times', function ($query) { $query->whereBetween('start_date', [new Carbon('2000-01-01 00:00:00'), new Carbon('2000-01-01 12:00:00'])) ->orWhereBetween('end_date', [new Carbon('2000-01-01 00:00:00'), new Carbon('2000-01-01 12:00:00'])) ->orWhereBetween('start_date', [new Carbon('2000-01-02 00:00:00'), new Carbon('2000-01-02 12:00:00'])) ->...etc,
猜你喜欢
  • 2019-02-23
  • 2014-01-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-08-28
相关资源
最近更新 更多