在Laravel中为一个模型定义多个全局范围


define multiple Global scope for a model in Laravel

我有一个具有SoftDelete功能的Post Model和一个活动布尔字段,用于确定Post活动状态。

class Post extends Model implements SluggableInterface
{
    use SoftDeletes;
    protected $primaryKey = 'post_id';
    .
    .
    .
 }

此外,Post Model还有一个start_date字段,用于保存发布Post的开始日期。

现在,除了非软删除模型之外,我想使用Anonymous GlobalScope Laravel 5.2来过滤和获取活动帖子,以及那些他们的start_date为NULL或小于now()的帖子。

为此,我将其添加到Post模型中:

protected static function boot()
        {
            parent::boot();
            static::addGlobalScope('active', function(Builder $builder){
                $builder->where('active',1);
            });
            static::addGlobalScope('scheduled', function(Builder $builder){
                $builder
                    ->whereNull('start_date')->orWhere(function ($query) {
                        $query->where('start_date', '<=', Carbon::now());
                    });
            });
        }

单独使用active全局作用域可以正常工作,但当我添加第二个名为scheduled的作用域时,会返回所有记录,包括softDeleted和inActive模型。

什么是问题?我听不懂

这是因为您使用的是orWhere。在这些情况下,使用Laravel调试栏查看Raw SQL非常有用,因为我敢打赌你的select语句看起来像这样:

SELECT * FROM table WHERE deleted_at IS NULL AND active=1 AND state_date IS NULL OR (start_Date <= now())

这将选择任何符合"一或"标准的内容。

要解决这个问题,您应该将scheduled设置为这样。

static::addGlobalScope('scheduled', function(Builder $builder) {
    $builder->where(function($query)) {
        $query->whereNull('start_date');
        $query->orWhere('start_date', '<=', Carbon::now());
    });
});

这将(希望)使您的查询看起来像这样:

SELECT * FROM table WHERE deleted_at IS NULL AND active=1 AND (state_date IS NULL OR start_Date <= now())

这就是我认为你想要的。