
本文详解如何在 php 中使用 pdo 时,确保特定数据库列(如 column2)在 json 序列化时始终作为字符串类型输出,避免数字被自动转为整型,从而解决 json_encode() 丢失前导零或类型不一致的问题。
本文详解如何在 php 中使用 pdo 时,确保特定数据库列(如 column2)在 json 序列化时始终作为字符串类型输出,避免数字被自动转为整型,从而解决 json_encode() 丢失前导零或类型不一致的问题。
在使用 PDO 查询数据库并输出 JSON 接口时,一个常见痛点是:数据库中定义为 INT、BIGINT 或 NUMERIC 的字段(例如订单号、编码、带前导零的编号),即使业务逻辑要求其始终以字符串形式暴露给前端,PDO 默认仍会将其映射为 PHP 数值类型(如 int 或 float),导致 json_encode() 输出无引号的纯数字——这不仅破坏了数据契约,更会导致 JavaScript 中前导零丢失(如 00930239 变成 930239)、大整数精度丢失(如超过 2^53 的 ID 被截断),甚至引发强类型前端框架(如 TypeScript + Axios)的类型校验失败。
你提供的代码片段中,问题根源在于:
foreach ($row as $rowvalue) {
strval($rowvalue["column2"]); // ❌ 仅计算结果,未赋值回数组!
}
该循环调用 strval() 后未将转换结果写回 $row 数组,因此 json_encode($row) 依然使用原始数值,毫无效果。
✅ 正确解决方案:启用 PDO::ATTR_STRINGIFY_FETCHES
PDO 提供了一个全局连接级属性——PDO::ATTR_STRINGIFY_FETCHES,启用后,PDO 会将所有从数据库获取的标量值(包括整数、布尔、NULL 等)统一转换为字符串类型,从根本上避免数值类型干扰 JSON 输出:
// 在创建 PDO 实例后,立即设置该属性(推荐)
$pdoConnect = new PDO($dsn, $user, $pass, [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
PDO::ATTR_STRINGIFY_FETCHES => true, // ✅ 关键:开启字符串化 fetch
]);
$stmt = $pdoConnect->prepare('SELECT column1, column2, column3 FROM table1 WHERE column1 = ?');
$stmt->execute(['tree']);
$rows = $stmt->fetchAll();
echo json_encode($rows, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT);
✅ 输出即为理想格式:
[
{
"column1": "tree",
"column2": "29012",
"column3": "foggy"
},
{
"column1": "tree",
"column2": "00930239",
"column3": "sunny"
}
]
⚠️ 注意事项:
- PDO::ATTR_STRINGIFY_FETCHES 是连接级设置,影响该 PDO 实例后续所有查询结果,不可按语句粒度开关;
- 它对 NULL、TRUE/FALSE 同样生效(分别转为 "null"、"1"、""),若需保留布尔/空值语义,应避免全局启用;
- 若仅需单列字符串化(如仅 column2,其余列保持原类型),则应改用手动映射方式:
? 替代方案:精准控制单列类型(推荐用于混合类型场景)
$stmt = $pdoConnect->prepare('SELECT column1, column2, column3 FROM table1 WHERE column1 = ?');
$stmt->execute(['tree']);
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
// 仅将 column2 强制转为字符串,保留其他字段原始类型
foreach ($rows as &$row) {
$row['column2'] = (string)$row['column2']; // ✅ 使用 (string) 强制类型转换,简洁可靠
}
unset($row); // 解除引用,防止意外修改
echo json_encode($rows, JSON_UNESCAPED_UNICODE);
此方式灵活、可控,且兼容所有 PDO 驱动(MySQL、PostgreSQL、SQL Server 等),无副作用。
? 总结建议
| 场景 | 推荐方案 | 说明 |
|---|---|---|
| 所有数值列均需字符串化(如统一对外提供字符串 API) | PDO::ATTR_STRINGIFY_FETCHES = true | 简洁高效,一劳永逸 |
| 仅特定列需字符串化(如 column2 为编码,column3 为状态码需保持 int) | 手动 (string)$row['column2'] | 精准可控,无全局影响 |
| 需保留前导零 + 高精度大数(如身份证、长订单号) | 必须使用字符串化(二者任选其一) | 数值类型无法表达前导零,int 在 JS 中会丢失精度 |
切记:永远不要依赖 strval() 无赋值的“假转换”,也无需复杂地调用 getColumnMeta() 判断类型——PDO 原生支持已足够成熟。合理利用 ATTR_STRINGIFY_FETCHES 或显式类型转换,即可优雅解决 JSON 类型一致性难题。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











