首页 > 解决方案 > 使用范围的 Laravel 集合过滤器

问题描述

我有下表:

积极的

id 开始_at 结束_at

我想每天获取所有活动,比较两个日期 starts_at 和 ends_at 并以天为单位获取差异,如下例所示:

Route::get('test', function(){
$dailyActives = \App\Models\Active::all()->filter(function ($active) {
   return $active->starts_at->diffInDays($active->ends_at) >= 1 && $active->starts_at->diffInDays($active->ends_at) <= 3;
});

dd($dailyActives);

});

它100%有效。

但我想重用这段代码,因为我有更多的模式,比如每日、每周、每月。

我的想法是在模型中创建一个范围,但我不能使用过滤器,因为 $query 不是一个集合。我尝试了以下代码:

/**
 * Scope a query to only include daily actives.
 *
 * @param \Illuminate\Database\Eloquent\Builder $query
 * @return \Illuminate\Database\Eloquent\Builder
 */
public function scopeDaily($query)
{
    $query->filter(function ($active) {
        if($active->starts_at->diffInDays($active->ends_at) >= 1 && $active->starts_at->diffInDays($active->ends_at) <=3) {
            return true;
        }
    });
}

那么有人可以推荐我最好的方法吗?也许使用范围以及如何使用?或创建一个可重用的类,例如,只需调用 Active::daily()->get() 我每天都会获得所有活动。

提前谢谢了!

标签: laraveleloquent

解决方案


您不需要使用过滤器。像这样使用范围$dailyActives = \App\Models\Active::interval('weekly')->get();

public function scopeInterval($query, $interval = 'daily')
{
    // daily
    $dateBetween = [now()->startOfDay(), now()->endOfDay()];

    if($interval === 'weekly'){
        $dateBetween = [now()->startOfWeek(), now()->endOfWeek()];
    }
    elseif($interval === 'month'){
        $dateBetween = [now()->startOfMonth(), now()->endOfMonth()];
    }

    $query->whereBetween('created_at', $dateBetween);
    
    return $query;
}

推荐阅读