Laravel查询:获取其中孩子的日期范围不在日期范围数组中的模型

时间:2018-12-18 09:34:02

标签: laravel laravel-5.7

我有Event个孩子hasMany个模型的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' ]

1 个答案:

答案 0 :(得分:1)

您可以创建一个新的query scope,以便在notInDateRange模型中创建一个Event范围,并在新范围内使用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中访问start_dateend_date列时使用Date Mutators将其转换为Carbon日期。为此,请将以下代码段添加到您的Event模型类中:

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