Laravel 中 Query Builder 与 Collection 有什么区别

Query Builder 是 SQL 构造器,操作发生在数据库;Collection 是 PHP 内存中的数组增强包装,操作发生在应用层。get() 是分水岭:之前是 Builder,之后是 Collection。

最佳实践
应用程序模块协作插画

一句话回答:Query Builder(查询构造器)用于在数据库层面构造和执行 SQL,where()、orderBy() 等调用最终翻译成 SQL 语句;Collection(集合)是数据取回内存后的增强数组,提供 map()、filter()、chunk() 等链式方法。get() 通常返回 Collection;first() 返回单个对象/模型或 null,paginate() 返回分页器,不能统称为 Collection。

版本范围:以下 Laravel 示例按 12.x 官方文档核对;其他版本请检查对应 API 与配置差异。

各是什么

Query Builder——应用与数据库之间的抽象层,提供跨数据库的统一 API:

$users = DB::table('users')
    ->where('votes', '>=', 100)   // 翻译成 SQL 的 WHERE
    ->orderBy('created_at')
    ->get();                       // ← 这一刻 SQL 才真正执行

Collection——对 PHP 数组的面向对象包装,提供流畅的链式数据处理:

$collection = collect(str_split('AABBCCCD'));

$chunks = $collection->chunkWhile(function ($value, $key, $chunk) {
    return $value === $chunk->last();
});

$chunks->map(fn ($chunk) => $chunk->values()->all())->all();
// [['A','A'], ['B','B'], ['C','C','C'], ['D']]

核心区别

维度 Query Builder Collection
操作位置 数据库(生成 SQL) PHP 内存
数据量 只取需要的数据 已取回的全部数据
典型方法 where() join() groupBy() get() map() filter() pluck() chunk()
性能特征 可利用索引,实际性能取决于执行计划 大集合占应用内存,小集合变换也可能更合适
求值 where/orderBy 构造查询,get/first 等触发执行 普通 Collection 通常已载入;LazyCollection 另有惰性语义

同名方法的不同语义——最容易踩的坑

Builder 和 Collection 都有 where()、pluck() 等方法,但行为完全不同:

// Builder:WHERE created_at > '2024-01-01' 下推到数据库,只取需要的行
DB::table('orders')->where('created_at', '>', '2024-01-01')->get();

// Collection:先 get() 取回全部 100 万行,再在内存里过滤 —— 灾难
DB::table('orders')->get()->where('created_at', '>', '2024-01-01');

原则:能在数据库做的事(过滤、排序、聚合、分页),绝不留到 Collection 里做。 Collection 适合的是取回后的变换、分组展示、计算派生数据。

Eloquent 的位置

Eloquent 模型查询返回的是 Illuminate\Database\Eloquent\Collection(继承自基础 Collection,多了模型相关方法如 load() 预加载)。User::where(...)->get() 先走 Builder,get() 后得到 Eloquent Collection,规则相同。

常见问题(FAQ)

Q:怎么判断当前链式调用的是 Builder 还是 Collection?

A:看终结方法与返回类型:Query Builder 的 get() 是基础 Collection,Eloquent 的 get() 是模型集合;first() 是 stdClass/模型或 null;paginate() 是 LengthAwarePaginator。可用 get_debug_type($x) 检查,null 不能传给 get_class()。

Q:DB::table() 和 User:: 查询有什么区别?

A:DB::table() 返回 Query Builder,调用 get() 才返回基础 Collection(元素是 stdClass);User::where() 返回 Eloquent Builder,get() 才返回模型集合。

Q:Collection 方法太多记不住怎么办?

A:可先熟悉这些常用方法:map filter pluck groupBy sortBy chunk first count sum toArray。其余用时查文档。

核查依据

本文依据官方文档核对,示例未在实际业务环境运行;上线前请按部署版本、权限与数据范围验证。


延伸阅读

获取专属方案

联系我们

加入社区

微信扫码
加入官方交流群

立即体验

在线开通,按量计费,真正的云服务!

立即开始

选择观测云版本

代码托管平台