应使用 result_array() 获取关联数组,在服务类中封装 totimestampvaluepairs() 方法转换为二维数值数组,避免在模型或控制器中硬编码,确保字段名大小写一致、null 值安全处理及时间戳精度。

CodeIgniter 里怎么把查询结果转成前端要的二维数组格式
直接用 result_array() 拿到的是关联数组,比如 ['date_issued' => '2021-03-01', 'grand_total' => '972.948'],但前端图表库(如 ECharts)常要 [[1614556800000, 972.948]] 这种纯数值二维数组。不手动转换,前端就得重复写解析逻辑。
关键不是“能不能转”,而是“在哪转、谁来转”——别塞进控制器里硬编码,也别在模型里 return 前做全量转换(破坏复用性)。推荐在服务类或专用格式化器里封装:
- 新建
app/Services/DataFormatter.php,定义静态方法toTimestampValuePairs() - 入参是
array $rows(来自$query->result_array()),指定字段名如'date_issued'和'grand_total' - 内部用
strtotime($row['date_issued']) * 1000转毫秒时间戳,用(float) $row['grand_total']强转数值 - 每行 push 一个
[$timestamp, $value]数组,最后返回二维数组
为什么不能直接在 Model 里调用 result() 返回对象再加工
CI 的 result() 返回对象数组,字段访问是 $row->date_issued,但对象属性无法用 isset() 安全判断,且 JSON 序列化时若字段含非法字符(如带空格的列别名),会静默丢数据甚至 panic。而 result_array() 返回标准 PHP 关联数组,isset($row['date_issued']) 可靠,json_encode() 兼容性更好。
更实际的问题是:SQL Server 或 MySQL 5.7+ 的 JSON 类型字段,在 result() 下可能被转成 StdClass 对象,嵌套深了容易触发 Serialization of 'stdClass' is not allowed 错误;result_array() 则自动展平为数组,更可控。
- 永远优先用
result_array()而非result()做格式转换起点 - 如果必须用对象(比如依赖 ORM 行为),先
json_decode(json_encode($row), true)强制转回数组 - 别在模型里直接
echo json_encode(...)—— 模型只负责取数据,不负责输出
封装统一响应结构时,Data 字段怎么塞才不 panic
CI 本身没 Gin 那种 c.JSON() 语义,但你仍需控制输出结构。常见翻车点:把数据库结果对象(如 CI_DB_result)直接塞进 Data,导致 json_encode() 失败;或传了未导出字段的 struct,序列化为空对象。
安全做法是显式构造响应数组,而不是依赖隐式转换:
- 响应结构固定为
['code' => 0, 'message' => 'ok', 'data' => []],data必须是可 JSON 编码的类型(array、string、int、float、null) - 从数据库来的原始数据,先过一遍
array_map('array_values', $rows)去掉键名,再用toTimestampValuePairs()加工 - 如果某字段可能为
null(如grand_total缺失),转floatval()而非(float),避免NaN进入 JSON - 别用
extract()或compact()动态拼响应 —— 字段名拼错不会报错,只会让前端收不到 key
CI3 和 CI4 在查询结果处理上有什么关键差异
CI3 的 $query->result_array() 返回二维关联数组,字段名全小写,兼容性好;CI4 的 $builder->get()->getResultArray() 行为一致,但如果你用了 Query Builder 的 select('DATE_FORMAT(created_at, "%Y-%m-%d") as date_str'),CI4 默认会保留别名大小写(如 date_str),而 CI3 有时会强制转小写,导致字段名不一致。
更隐蔽的坑是:CI4 默认开启严格模式,getResultArray() 遇到 NULL 字段会保持 null 值,而某些 CI3 驱动(尤其是 SQL Server)可能把 NULL 转成空字符串,造成前后端类型不一致。
- 跨版本迁移时,用
var_dump(array_keys(reset($rows)))确认字段名实际大小写 - 对可能为
null的数值字段,统一用coalesce(grand_total, 0)在 SQL 层兜底,比 PHP 层判断更稳 - CI4 推荐用
getCompiledSelect()打印最终 SQL,验证字段别名是否符合预期
真正卡住进度的往往不是语法,而是字段名大小写、null 值处理、时间戳精度这三处——它们不出错则已,一错就是前端白屏或图表不渲染,且日志里几乎不报错。











