0

0

掌握 Laravel 查询构建器中的条件查询技巧

心靈之曲

心靈之曲

发布时间:2025-11-29 11:09:19

|

236人浏览过

|

来源于php中文网

原创

掌握 laravel 查询构建器中的条件查询技巧

本文深入探讨了在 Laravel 8 中利用查询构建器(Query Builder)或 Eloquent 进行动态搜索的最佳实践。针对根据可选请求参数构建复杂查询的场景,文章详细介绍了如何使用 `when` 方法优雅地实现条件查询,避免冗余的 `if` 语句,从而编写出更简洁、可读性更强的代码。

在开发基于 Laravel 的应用程序时,经常需要根据用户提供的可选参数(例如搜索关键词、筛选条件等)动态构建数据库查询。传统的做法是使用一系列 if 语句来判断参数是否存在,然后有条件地向查询链中添加 where 子句。然而,这种方法在面对多个可选条件时,可能导致代码冗长且难以维护。Laravel 提供了一种更为优雅和强大的解决方案:when 方法。

动态查询构建的挑战

考虑一个常见的场景:用户可以通过 URL 查询字符串(如 ?q=john&gender=m)来搜索用户列表。如果 q 或 gender 参数不存在,则不应将其作为查询条件。

初始的尝试可能如下所示:

public function index (Request $request)
{
    $role = getRoleCode($request->role);
    $rolesQuery = Role::where('role', '=', $role); // 注意:这里应是 $rolesQuery 而非 $roles

    if ($request->q) {
        // 错误:$request->$q 是错误的变量引用方式
        $rolesQuery->where('name', 'like', "%$request->$q%");
    }

    if ($request->gender) {
        $rolesQuery->where('gender', '=', $request->gender);
    }

    // 在实际执行查询之前,可能需要将结果赋值给一个变量
    $roles = $rolesQuery->orderBy('id', 'desc')->paginate(20);

    return view('admin.users.index', [
        'roles' => $roles,
        // ... 其他视图数据
    ]);
}

上述代码中存在几个问题:

  1. 变量命名不一致,$roles 在条件语句中被当做查询构建器实例,但在最后又被赋值为分页结果。
  2. $request->$q 是一种错误的变量引用方式,正确的应是 $request->q 或 $request->input('q')。
  3. 虽然 if 语句可以实现条件查询,但当条件增多时,代码的层级和复杂度会增加,降低可读性。

优雅的解决方案:使用 when 方法

Laravel 的查询构建器和 Eloquent 模型都提供了 when 方法,用于实现条件性地向查询中添加子句。when 方法的签名如下:

你好星识
你好星识

你的全能AI工作空间

下载
when(mixed $value, callable $callback, callable $default = null): static

它接受三个参数:

  1. $value:一个用于判断条件的布尔值或可以被评估为布尔值的值。如果此值为 true(或“真值”),则执行第二个参数 $callback。
  2. $callback:一个闭包函数,它将接收当前查询构建器实例作为第一个参数,以及 $value 作为第二个参数(如果 $value 是一个非布尔值且为真)。
  3. $default (可选):如果 $value 为 false(或“假值”),则执行此闭包函数。

利用 when 方法,我们可以将上述动态查询重构为以下简洁且高效的形式:

role);

        $roles = Role::where('role', $roleCode)
            // 当 $request->input('q') 非空时,执行闭包添加 name 搜索条件
            ->when($request->input('q'), function ($query, $search) {
                return $query->where('name', 'like', '%' . $search . '%');
            })
            // 当 $request->input('gender') 非空时,执行闭包添加 gender 筛选条件
            ->when($request->input('gender'), function ($query, $gender) {
                return $query->where('gender', $gender);
            })
            ->orderBy('id', 'DESC')
            ->paginate(20);

        return view('admin.users.index', [
            'roles' => $roles,
            'role_name' => config('settings.roles')[$roleCode], // 假设配置存在
            'role_en_name' => $request->role,
            'q' => $request->input('q'),
            'gender' => $request->input('gender'),
        ]);
    }

    // 假设这是一个辅助函数,用于获取角色代码
    protected function getRoleCode($roleName)
    {
        // 实现根据角色名称获取角色代码的逻辑
        // 例如:
        switch ($roleName) {
            case 'supervisor': return 'SUP';
            case 'admin': return 'ADM';
            default: return 'USR';
        }
    }
}

代码解析:

  1. Role::where('role', $roleCode):这是所有查询的基础条件。
  2. ->when($request->input('q'), function ($query, $search) { ... }):
    • $request->input('q'):安全地从请求中获取 q 参数的值。如果 q 参数不存在或为空字符串,input() 方法将返回 null 或空字符串,这在布尔上下文中被评估为 false。
    • function ($query, $search) { ... }:这是一个闭包函数。
      • $query:代表当前的查询构建器实例。
      • $search:如果 $request->input('q') 的值是“真值”,那么 $search 将接收到 $request->input('q') 的实际值。
      • return $query->where('name', 'like', '%' . $search . '%');:在这个闭包中,我们向查询中添加了 name 字段的模糊搜索条件。务必从闭包中返回 $query 实例,以便继续链式调用。
  3. ->when($request->input('gender'), function ($query, $gender) { ... }):同理,这会根据 gender 参数的值添加精确匹配条件。
  4. ->orderBy('id', 'DESC')->paginate(20):最后,应用排序和分页。

注意事项与最佳实践

  • 使用 $request->input():始终建议使用 $request->input('param_name') 来获取请求参数,因为它比 $request->param_name 更健壮,可以处理 GET 和 POST 请求,并且在参数不存在时返回 null 而不是抛出错误。
  • 链式调用:when 方法的强大之处在于它保持了查询构建器的链式调用特性,使得代码流程清晰。
  • 闭包返回值:在 when 方法的闭包中,一定要返回修改后的 $query 实例,否则后续的链式操作将无法生效。
  • 可读性:when 方法显著提高了代码的可读性和简洁性,特别是当有多个可选条件时。
  • PHP 7.4+ 箭头函数:如果你的项目使用 PHP 7.4 或更高版本,可以使用箭头函数进一步简化闭包的写法,如示例答案中所示:fn ($query, $search) => $query->where('name', 'like', '%'. $search .'%')。

总结

Laravel 的 when 方法是处理动态条件查询的利器,它提供了一种优雅、高效且可读性强的方式来构建复杂的数据库查询。通过合理运用 when 方法,开发者可以避免冗余的 if 语句,使控制器代码更加简洁和专业,从而提升应用程序的可维护性和开发效率。掌握这一技巧对于任何 Laravel 开发者来说都至关重要。

相关专题

更多
php文件怎么打开
php文件怎么打开

打开php文件步骤:1、选择文本编辑器;2、在选择的文本编辑器中,创建一个新的文件,并将其保存为.php文件;3、在创建的PHP文件中,编写PHP代码;4、要在本地计算机上运行PHP文件,需要设置一个服务器环境;5、安装服务器环境后,需要将PHP文件放入服务器目录中;6、一旦将PHP文件放入服务器目录中,就可以通过浏览器来运行它。

2528

2023.09.01

php怎么取出数组的前几个元素
php怎么取出数组的前几个元素

取出php数组的前几个元素的方法有使用array_slice()函数、使用array_splice()函数、使用循环遍历、使用array_slice()函数和array_values()函数等。本专题为大家提供php数组相关的文章、下载、课程内容,供大家免费下载体验。

1604

2023.10.11

php反序列化失败怎么办
php反序列化失败怎么办

php反序列化失败的解决办法检查序列化数据。检查类定义、检查错误日志、更新PHP版本和应用安全措施等。本专题为大家提供php反序列化相关的文章、下载、课程内容,供大家免费下载体验。

1496

2023.10.11

php怎么连接mssql数据库
php怎么连接mssql数据库

连接方法:1、通过mssql_系列函数;2、通过sqlsrv_系列函数;3、通过odbc方式连接;4、通过PDO方式;5、通过COM方式连接。想了解php怎么连接mssql数据库的详细内容,可以访问下面的文章。

952

2023.10.23

php连接mssql数据库的方法
php连接mssql数据库的方法

php连接mssql数据库的方法有使用PHP的MSSQL扩展、使用PDO等。想了解更多php连接mssql数据库相关内容,可以阅读本专题下面的文章。

1416

2023.10.23

html怎么上传
html怎么上传

html通过使用HTML表单、JavaScript和PHP上传。更多关于html的问题详细请看本专题下面的文章。php中文网欢迎大家前来学习。

1234

2023.11.03

PHP出现乱码怎么解决
PHP出现乱码怎么解决

PHP出现乱码可以通过修改PHP文件头部的字符编码设置、检查PHP文件的编码格式、检查数据库连接设置和检查HTML页面的字符编码设置来解决。更多关于php乱码的问题详情请看本专题下面的文章。php中文网欢迎大家前来学习。

1445

2023.11.09

php文件怎么在手机上打开
php文件怎么在手机上打开

php文件在手机上打开需要在手机上搭建一个能够运行php的服务器环境,并将php文件上传到服务器上。再在手机上的浏览器中输入服务器的IP地址或域名,加上php文件的路径,即可打开php文件并查看其内容。更多关于php相关问题,详情请看本专题下面的文章。php中文网欢迎大家前来学习。

1306

2023.11.13

公务员递补名单公布时间 公务员递补要求
公务员递补名单公布时间 公务员递补要求

公务员递补名单公布时间不固定,通常在面试前,由招录单位(如国家知识产权局、海关等)发布,依据是原入围考生放弃资格,会按笔试成绩从高到低递补,递补考生需按公告要求限时确认并提交材料,及时参加面试/体检等后续环节。要求核心是按招录单位公告及时响应、提交材料(确认书、资格复审材料)并准时参加面试。

0

2026.01.15

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
PHP课程
PHP课程

共137课时 | 8.6万人学习

JavaScript ES5基础线上课程教学
JavaScript ES5基础线上课程教学

共6课时 | 7万人学习

PHP新手语法线上课程教学
PHP新手语法线上课程教学

共13课时 | 0.9万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号