在使用PDO操作mysql数据库时,我们经常会发现查询返回的整型字段变成了String类型,比如数据库里存储的用户ID是整型的1,查询后拿到的却是字符串"1",这种情况会给后续的数值计算、类型校验带来麻烦,下面我们就来分析原因并给出对应的解决方法。

问题产生的原因
PDO默认情况下,从mysql获取数据时会将所有的字段值都作为字符串返回,这是因为mysql的客户端协议在传输数据时会把数值类型先转为文本格式,而PDO默认不会做自动的类型映射,所以整型、浮点型这类数值字段都会被转为String类型。另外如果PDO连接时设置了PDO::ATTR_EMULATE_PREPARES为true,也会加剧这个问题,因为模拟预处理时参数和结果的类型处理会更偏向字符串化。
解决方法一:修改PDO连接属性
可以在创建PDO连接的时候,设置两个关键属性,让PDO自动将数值类型的字段转为对应的php数值类型,具体设置如下:
<?php
// 数据库配置
$host = '127.0.0.1';
$dbname = 'test';
$username = 'root';
$password = '123456';
try {
// 创建PDO连接,设置属性
$pdo = new PDO(
"mysql:host=$host;dbname=$dbname;charset=utf8",
$username,
$password,
[
// 禁用模拟预处理,使用原生预处理
PDO::ATTR_EMULATE_PREPARES => false,
// 设置结果集返回时自动转换数值类型
PDO::ATTR_STRINGIFY_FETCHES => false
]
);
// 执行查询
$stmt = $pdo->query("SELECT id, age FROM user WHERE id = 1");
$result = $stmt->fetch(PDO::FETCH_ASSOC);
// 此时id和age都会是整型
var_dump($result['id']); // 输出 int(1)
var_dump($result['age']); // 输出 int(20)
} catch (PDOException $e) {
echo "数据库连接失败:" . $e->getMessage();
}
?>
这里要注意PDO::ATTR_EMULATE_PREPARES设为false是使用mysql原生预处理,配合PDO::ATTR_STRINGIFY_FETCHES设为false,就能让PDO自动识别数值类型并转换,不过这个方式依赖于mysql驱动的版本,部分旧版本驱动可能不支持自动转换。
解决方法二:查询后手动转换类型
如果修改连接属性无法满足需求,也可以在拿到查询结果后,手动对需要的字段做类型转换,这种方式兼容性更好,适合所有PDO版本:
<?php
// 假设已经创建了PDO连接$pdo
$stmt = $pdo->query("SELECT id, age, name FROM user");
$list = $stmt->fetchAll(PDO::FETCH_ASSOC);
// 定义需要转为整型的字段列表
$intFields = ['id', 'age'];
foreach ($list as &$item) {
foreach ($intFields as $field) {
if (isset($item[$field]) && is_numeric($item[$field])) {
// 转为整型
$item[$field] = (int)$item[$field];
}
}
}
unset($item);
// 此时id和age已经是整型
var_dump($list[0]['id']); // int(1)
?>
这种方式可以精确控制需要转换的字段,避免不必要的类型转换,比如如果某个字段是字符串类型的数字,你不希望它转成整型,就可以不加入转换列表。
解决方法三:使用mysql函数转换字段类型
还可以在sql查询语句中,使用mysql的CAST或者CONVERT函数,直接把字段转换为数值类型,这样PDO拿到的结果就会是数值类型:
<?php // 使用CAST函数将id和age转为有符号整型 $sql = "SELECT CAST(id AS SIGNED) as id, CAST(age AS SIGNED) as age, name FROM user"; $stmt = $pdo->query($sql); $result = $stmt->fetch(PDO::FETCH_ASSOC); var_dump($result['id']); // 输出 int(1) var_dump($result['age']); // 输出 int(20) ?>
这种方式的优点是不需要修改php代码的逻辑,直接在sql层面处理,但是会增加sql语句的复杂度,如果查询的字段比较多,写起来会比较繁琐。
方法选择建议
如果是新项目,优先选择修改PDO连接属性的方式,配置一次全局生效,代码更简洁;如果是旧项目不便修改全局连接配置,或者只需要对部分查询做处理,选择手动转换或者sql函数转换的方式更稳妥。另外要注意,如果字段可能为null,做类型转换前要先判断是否为null,避免出现转换错误。