如何在 Laravel Eloquent 中构建复杂 WHERE 条件:4 种方法及示例

面向初学者的在线Python训练器

轻松学习Python,无需理论负担。在浏览器中直接解决带自动检查的实践任务,无需安装任何东西。

开始课程

如何在 Laravel Eloquent 中构建复杂 WHERE 条件:4 种方法及示例

\n\n

想象一下:您正在用 Laravel 开发一个在线商店。需要找出所有价格在 1000 到 5000 卢布之间、有库存、但不属于“促销”类别,并且创建于 2024 年 1 月 1 日之后的商品。如何通过一次查询完成,同时不影响性能?

\n\n

这个问题是 Stack Overflow 上最热门的问题之一(浏览量成千上万!)。这并非偶然:在 Laravel Eloquent 中构建复杂 WHERE 条件的能力,是区分新手和生产级开发者的关键。

\n\n

在本文中,我将向您展示4 种经过验证的方法来创建多重 WHERE 条件。您将了解何时使用数组,何时使用闭包,如何对条件进行分组,以及如何防止 SQL 注入。让我们开始吧!

\n\n
\n\n

1. 基础方法:条件数组(适用于简单的 AND 条件)

\n\n

最简单的情况是所有条件通过 AND 连接。Laravel 允许您向 where() 传递一个普通数组:

\n\n
<?php\n\n// 想要查找 2024 年创建的、来自俄罗斯的活跃用户\n$users = User::where([\n    ['status', '=', 'active'],\n    ['country', '=', 'Russia'],\n    ['created_at', '>=', '2024-01-01'],\n])->get();\n\n// SQL: SELECT * FROM users WHERE status = 'active' AND country = 'Russia' AND created_at >= '2024-01-01'
\n\n

何时使用:当您有 2-5 个使用 = 或 > 运算符的简单条件时。代码可读性强,但不够灵活。

\n\n

缺点:如果需要混合使用 AND 和 OR,数组方法不适用。

\n\n

2. 链式调用 where() 方法(适用于动态条件)

\n\n

这是开发者中最流行的方法。您只需连续多次调用 where():

\n\n
<?php\n\n$products = Product::where('price', '>', 1000)\n    ->where('price', '<', 5000)\n    ->where('in_stock', true)\n    ->where('category_id', '!=', 5)\n    ->get();\n\n// SQL: ... WHERE price > 1000 AND price < 5000 AND in_stock = 1 AND category_id <> 5
\n\n

技巧:您可以与其他条件组合:

\n\n
<?php\n\n// 链式调用中的“OR”条件\n$orders = Order::where('status', 'paid')\n    ->orWhere('status', 'shipped')\n    ->where('total', '>', 100)  // 注意:此条件应用于前面的 orWhere!\n    ->get();\n\n// SQL: ... WHERE status = 'paid' OR (status = 'shipped' AND total > 100)
\n\n

⚠️ 重要!在最后一个示例中,where total > 100 仅应用于 status = 'shipped'。如果您希望两个状态都满足 total > 100 的条件,请阅读下一节。

\n\n

3. 通过闭包对条件进行分组(同时使用 AND 和 OR)

\n\n

现在我们接触到最强大的工具。当需要在括号内创建一组条件时,请在 where() 内部使用闭包:

\n\n
<?php\n\n// 任务:查找状态为“paid”或“shipped”的订单,\n// 但两种情况下的 total 都必须 > 100\n$orders = Order::where(function($query) {\n        $query->where('status', 'paid')\n              ->orWhere('status', 'shipped');\n    })\n    ->where('total', '>', 100)\n    ->get();\n\n// SQL: ... WHERE (status = 'paid' OR status = 'shipped') AND total > 100
\n\n

现在条件被正确分组了!您可以任意嵌套闭包:

\n\n
<?php\n\n// 用于分析功能的复杂过滤器\n$data = Sale::where('date', '>=', '2024-01-01')\n    ->where(function($q) {\n        $q->where('amount', '>', 10000)\n          ->orWhere('is_vip', true);\n    })\n    ->where(function($q) {\n        $q->                

博客

书籍推荐