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

时间:2016-05-01 13:37:04

标签: php laravel

我有一个具有 SoftDelete 功能的帖子模型和一个活动布尔字段来确定帖子活动状态。

class Post extends Model implements SluggableInterface
{
    use SoftDeletes;

    protected $primaryKey = 'post_id';
    .
    .
    .
 }

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

现在,我想使用Anonymous GlobalScope Laravel 5.2过滤和获取只有活动的帖子,他们的start_dat e是NULL或小于Now()除了非Soft Deleted模型。

为此我将其添加到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的第二个范围时,返回所有记录包括soft Deleted和inActive模型。

什么是问题?我无法理解

1 个答案:

答案 0 :(得分:1)

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

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

这将选择符合一个OR标准的任何东西。

要解决此问题,您应该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())

我认为你想要的是什么。