laravel 中 queryScope 的复杂查询约束

Complex query constraint on queryScope in laravel

用户 table 有以下列:

  1. created_at(时间戳)
  2. last_order(时间戳)

创建新用户时,last_order 为空,created_at 为当前时间戳。 当用户下订单时,最后一个订单列将更新为下订单时间的时间戳。 现在我想检索过去 7 天未下任何订单的所有用户。我定义我的用户模型如下:

class User extends Model
{
    /**
     * @var string The database table used by the model.
     */
    public $table = 'users';

    /**
     * @var array Validation rules
     */
    public $rules = [
    ];
    public $hasMany  = [
        'voucher' => ['ItScholarBd\Api\Models\Voucher'],
        'order' => ['ItScholarBd\Api\Models\OrderLog']
    ];

   public function scopeCustomer($query)
    {
        return $query->where('role_id', '=', 5);
    }
   public function scopeNew($query,$days)
    {
        return $query->where('created_at', '>=', Carbon::now()->subDays($days));
    }
   public function scopeIdle($query,$days)
   {

       $dayOffset = Carbon::now()->subDays($days);

      return $query->where(function($q,$dayOffset){
        $q->whereNull('last_order')
          ->where('created_at','<',$dayOffset);
       })->orWhere(function($q,$days){
        $q->whereNotNull('last_order')
        ->whereRaw("DATEDIFF(created_at,last_order)>$days");
       });

   } 

}

此处 scopeNew() 运行良好,但 scopeIdle() 抛出以下错误:

Type error: Too few arguments to function App\User::App\{closure}(),
  1 passed in .\vendor\laravel\framework\src\Illuminate\Database\Eloquent\Builder.php on line 222 and exactly 2 expected

尝试使用闭包:

return $query->where(function($q) use ($dayOffset){

您无法为您无法控制的功能编造参数。闭包将传递一个参数,您需要使用 use:

导入任何其他变量

public function scopeIdle($query, $days)
{
    $dayOffset = Carbon::now()->subDays($days);

    return $query
        ->where(function ($q) use ($dayOffset) {
            $q->whereNull('last_order')
                ->where('created_at', '<', $dayOffset);
        })
        ->orWhere(function ($q) use ($days) {
            $q->whereNotNull('last_order')
                ->whereRaw("DATEDIFF(created_at, last_order) > ?", [$days]);
       });
}

注意whereRaw语句中参数的使用,可以避免SQL注入。如果您始终如一地缩进 space,您还会发现您的代码更易于处理。