Laravel在哪里有条件的地方有回调

时间:2016-03-03 21:36:53

标签: php mysql sql laravel

我正在使用Laravel 5.2创建一般搜索功能,我希望显示搜索关键字出现的所有书籍:书的标题,书的主题,书的情节,书的作者姓名,书籍的作者姓氏; 我认为这段代码可行:

$results = Book::whereHas('author', function ($query) use ($keyword)
                     {
                          $query->where('surname', 'LIKE', '%'.$keyword.'%')
                               ->orWhere('name', 'LIKE', '%'.$keyword.'%');
                     })
                     ->orWhere('title', 'LIKE', '%'.$keyword.'%')
                     ->orWhere('plot', 'LIKE', '%'.$keyword.'%')
                     ->orWhere('subject', 'LIKE', '%'.$keyword.'%')
                     ->get();

但是当我使用作为关键字的作者的名字时,我得到整个库的结果。 相反,如果我输入一个作者的姓氏,那就完美了。

我发现了这个解决方案,在我看来并不是最优的,但至少它起作用了:

$results = Book::whereHas('author', function ($query) use ($keyword)
                     {
                          $query->where('surname', 'LIKE', '%'.$keyword.'%');
                     })
                     ->orWhereHas('author', function ($query) use ($keyword)
                     {
                          $query->where('name', 'LIKE', '%'.$keyword.'%');
                     })
                     ->orWhere('title', 'LIKE', '%'.$keyword.'%')
                     ->orWhere('plot', 'LIKE', '%'.$keyword.'%')
                     ->orWhere('subject', 'LIKE', '%'.$keyword.'%')
                     ->get();

有什么建议吗? 提前感谢您的帮助!

2 个答案:

答案 0 :(得分:4)

问题是你的闭包中添加的where子句不是唯一应用于子查询的where子句。 whereHas()方法生成一个子查询,该子查询以关系的ID的where子句开头。因此,您的子查询不仅仅是where x or y,实际上是where x and y or z

给定where子句的这一组,以及逻辑运算符的运算顺序,如果z条件为真(你的名字'条件),则整个where子句将返回true,意味着仅仅查看相关对象的约束被完全忽略。由于忽略了对相关对象的约束,因此has条件对于每条记录都是正确的(如果' name'匹配任何记录)。

以下是您的逻辑条件示例:

// first boolean is the related keys check
// second boolean is the surname check
// third boolean is the name check

// this is your current logic
// as you can see, this returns true even when looking at an
// author not even related to the book.
var_export(false && false || true); // true

// this is what your logic needs to be
var_export(false && (false || true)); // false

因此,要解决此问题,您需要将or条件包含在括号中,以便按照您的意图对它们进行评估。你可以通过将一个闭包传递给where()方法,然后在闭包内添加的任何条件都在括号内:

$results = Book::whereHas('author', function ($query) use ($keyword) {
        $query->where(function ($q) use ($keyword) {
            $q->where('surname', 'LIKE', '%'.$keyword.'%')
                ->orWhere('name', 'LIKE', '%'.$keyword.'%');
        });
    })
    ->orWhere('title', 'LIKE', '%'.$keyword.'%')
    ->orWhere('plot', 'LIKE', '%'.$keyword.'%')
    ->orWhere('subject', 'LIKE', '%'.$keyword.'%')
    ->get();

答案 1 :(得分:-2)

您是否尝试为作者/用户模型创建本地查询范围,例如named()然后应用

public function scopeNamed($query)
{
    return $query->where('surname', 'LIKE', '%'.$keyword.'%')
                 ->orWhere('name', 'LIKE', '%'.$keyword.'%');
}

然后你的查询

$results = Book::whereHas('author', function ($query) use ($keyword)
                 {
                      $query->named();
                 })
                 ->orWhere('title', 'LIKE', '%'.$keyword.'%')
                 ->orWhere('plot', 'LIKE', '%'.$keyword.'%')
                 ->orWhere('subject', 'LIKE', '%'.$keyword.'%')
                 ->get();

https://laravel.com/docs/master/eloquent#query-scopes