问题
在一次debug过程中发现,一样的代码在生产环境与开发环境运行的结果不一致,差异数据如下:
开发环境
array(7) {
["id"]=>
string(1) "1"
["month"]=>
string(6) "202302"
["create_time"]=>
string(19) "2021-12-21 15:49:12"
}
生产环境
array(7) {
["id"]=>
int(1)
["month"]=>
int(202302)
["create_time"]=>
string(19) "2021-12-21 15:49:12"
}
对比数据发现,在开发环境MySQL数据库里面查询出来的int类型转换成为了string。
追查
一样的代码,一样的数据库实例,所以可以初步判断是生产环境与测试环境的MySQL驱动不一致导致的,经过搜索,查看相关配置发现是PDO驱动版本不一致,默认的属性不一样,具体受影响的参数:
PDO::ATTR_EMULATE_PREPARES (启用或禁用预处理语句的模拟)
PDO::ATTR_STRINGIFY_FETCHES (提取的时候将数值转换为字符串)
验证
$pdo = new PDO($dsn, $user, $pass, $options);
/* 测试1, 结果 int 不转为 string */
$pdo->setAttribute(PDO: :ATTR EMULATE PREPARES,false);
$pdo->setAttribute(PDO::ATTR STRINGIFY FETCHES, false);
/* 测试2, 结果 int 转为 string */
$pdo->setAttribute(PDO: :ATTR EMULATE PREPARES,false);
$pdo->setAttribute(PDO: :ATTR STRINGIFY FETCHES, true);
/* 测试3, 结果 int 转为 string */
$pdo->setAttribute(PDO::ATTR EMULATE PREPARES,true);
$pdo->setAttribute(PDO: :ATTR STRINGIFY FETCHES, true);
/* 测试4, 结果 int 转为 string */
$pdo->setAttribute(PDO: :ATTR EMULATE PREPARES,true);
$pdo->setAttribute( PDO: :ATTR STRINGIFY FETCHES, false);
修复
项目使用的是Yii2框架,所以在数据库连接配置处,设置PDO参数即可:
'db' => [
'class' => 'yii\db\Connection',
'dsn' => 'mysql:host=127.0.0.1;dbname=test',
'username' => 'test',
'password' => 'xxxx',
'charset' => 'utf8mb4',
'attributes' => [
PDO::ATTR_EMULATE_PREPARES => false, // 禁用模拟预处理语句
PDO::ATTR_STRINGIFY_FETCHES => false,
],
],