为何Eloquent查询全部与带where子句的查询返回结果存在差异?
为什么Eloquent全量查询和带Where的查询返回JSON格式不同?
这问题我之前排查过,核心原因出在Eloquent Collection的索引连续性以及Laravel对JSON序列化的处理逻辑上,具体拆解如下:
1. 全量查询返回带0/2标识的原因
当你执行Model::all()或者Model::get()这类全量查询时,返回的是一个Eloquent Collection对象。如果你的数据库表中存在主键不连续的情况(比如删除过部分记录,或者数据是从其他地方导入的非连续ID),或者你对集合做过filter()/reject()这类会打乱原有索引的操作,那么这个Collection的索引就会变成非连续的整数(比如0、2、3...跳过了1)。
Laravel在将这类非连续索引的集合序列化为JSON时,会把它当作关联数组处理,最终输出的JSON就会带上这些索引作为键,比如:
{ "0": {"id": 1, "name": "xxx"}, "2": {"id": 3, "name": "yyy"} }
2. 带Where子句的查询返回正常数组的原因
而当你添加where子句后,数据库层面会直接过滤出符合条件的记录,并且Eloquent会按查询结果的顺序重新生成连续的索引(0、1、2...)。这类连续索引的集合在JSON序列化时,Laravel会把它当作索引数组处理,最终输出就是你期望的纯数组格式:
[{"id": 2, "name": "zzz"}, {"id": 4, "name": "aaa"}]
验证与解决方法
验证你的情况
可以在代码里加两行调试代码确认:
// 全量查询结果 $allResults = Model::all(); dd($allResults->isAssoc()); // 如果返回true,说明是关联数组(非连续索引) // 带Where的查询结果 $whereResults = Model::where('xxx', 'yyy')->get(); dd($whereResults->isAssoc()); // 应该返回false,是索引数组
解决方法
如果想让全量查询也返回纯数组格式的JSON,只需要用values()方法重置集合的索引即可:
// 重置索引后,序列化就会变成纯数组 return Model::all()->values();
内容的提问来源于stack exchange,提问作者Jk33
相关产品推荐
相关产品推荐

