Laravel 5.3 - 以 orWhere 开头的查询生成器

Laravel 5.3 - Query Builder starting with orWhere

最近Laravel发布了5.3版本。

下面link有一些从5.2升级到5.3的说明: https://laravel.com/docs/5.3/upgrade#upgrade-5.3.0

Eloquent scopes now respect the leading boolean of scope constraints. For example, if you are starting your scope with an orWhere constraint it will no longer be converted to normal where. If you were relying on this feature (e.g. adding multiple orWhere constraints within a loop), you should verify that the first condition is a normal where to avoid any boolean logic issues.

If your scopes begin with where constraints no action is required. Remember, you can verify your query SQL using the toSql method of a query:

这似乎让事情变得有点困难,升级只会增加限制。

我们有一个内部包,为了使代码尽可能简单和整洁,有一个部分依赖于使用 orWhere() 开始查询,并利用它以及一个内部的闭包概念递归方法。如您所知,递归方法最好保持简短。

根据现在的升级说明,Laravel 5.3

肯定会失败

我只是想知道是否有人知道删除此行为的原因?

谢谢!

更新:

我已经将我们的系统迁移到 Laravel 5.3。我确认这仅在 Eloquent 生成器中受到影响,而不在查询生成器(以前的 "Fluent Builder")中受到影响。

甚至提交(这是一个地狱般的大量更改)也仅在 Eloquent\Builder 上进行。 https://github.com/laravel/framework/issues/14829

无论如何,为了安全起见,我建议您进行相应的调整。这就是我们所做的,尽管我们知道它并没有破坏我们的代码(截至今天)。

我相信原因正是这个拉取请求:https://github.com/laravel/framework/pull/12918

有人想使用这样的范围:

User::approved()->orActive();

在这种情况下,如果 orActive 范围定义如下:

public function scopeOrActive($q) {
   return $q->orWhere('active',1)
}

approved作用域定义如下:

public function scopeApproved($q) {
   return $q->where('approved',1)
}

在 laravel 5.2 中它将解析为:

where approved = 1 AND active = 1

并在 Laravel 5.3 中解析为:

where approved = 1 OR active = 1

所以这是有道理的,但我从未使用过以 orWhere

开头的范围

这是一种使用布尔值的多个 orWhere 子句的方法。假设您想进行如下查询:

select * 来自 active = 1 and (user_type = 1 or user_type = 2 or user_type = 3);

但我们不一定总是希望所有 user_type 都在查询中,即我们有一些布尔值来决定哪些应该出现。这可以像这样实现:

$includeOne = true;
$includeTwo = false;
$includeThree = true;
$query = User::where('active', 1)
    ->where(function($q) use ($includeOne, $includeTwo, $includeThree) {
        $q->when($includeOne, function($query) {
            return $query->orWhere('user_type', 1);
        })
        ->when($includeTwo, function($query) {
            return $query->orWhere('user_type', 2);
        })
        ->when($includeThree, function($query) {
            return $query->orWhere('user_type', 3);
        });
    })->get();