php - Laravel 多个 where 条件在 whereHas 回调

标签 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();

有什么建议吗? 预先感谢您的帮助!

最佳答案

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

给定这组 where 子句和逻辑运算符的操作顺序,如果 z 条件为真(您的“姓名”条件),则整个 where 子句将返回真,这意味着完全忽略只查看相关对象的约束。由于忽略了对相关对象的约束,因此 has 条件对于每条记录都为真(如果“名称”匹配任何记录)。

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

// 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

因此,要解决此问题,您需要将 条件括在括号中,以便按您的预期对其进行评估。您可以通过将闭包传递给 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();

关于php - Laravel 多个 where 条件在 whereHas 回调,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35783539/

相关文章:

php - 如何在不使用 OAuth 的情况下制作安全 API?

mysql - 将 MMM-YY 字符串转换为可排序日期格式

c# - Linq Left join, where, group by, count()

mysql - 创建带有参数的Mysql View

mysql - 无法添加外键约束

mysql - SQL-从表中获取在两列中共享一个值的所有记录

php - 学说查询中唯一的商店ID

php - CakePHP 对 SQL Server 查找的响应缓慢

sockets - PHP 套接字 - socket_sendto() - UDP header 不匹配

php - 仅对所有 4 个表成功插入或根本不插入