Thinkphp5使用sqlite3作为数据库无法存储小数点的解决方案
在tp的官网搜了一下资料,主要是因为TP5自动绑定内型的时候自动将一些浮点数等类型的数字强制将PDO类型设置为了INT类型,而使用SQLITE数据库时,添加的语句遇到小数的时候就没有加上双引号,所以在写入数据的时候就自动把小数点后面的截断了。
thinkphp\library\think\db\Query.php 自动绑定类型的相关代码
protected function getFieldBindType($type)
{
if (0 === strpos($type, 'set') || 0 === strpos($type, 'enum')) {
$bind = PDO::PARAM_STR;
} elseif (preg_match('/(int|double|float|decimal|real|numeric|serial|bit)/is', $type)) {
$bind = PDO::PARAM_INT;
} elseif (preg_match('/bool/is', $type)) {
$bind = PDO::PARAM_BOOL;
} else {
$bind = PDO::PARAM_STR;
}
return $bind;
}
生成的建表语句如下,可以看到小数并没有引号,所以插入失败。
INSERT INTO dc_pay (pay_name , pay_sign , pay_info_id , pay_user_id , pay_price , pay_quantity , pay_total_fee , pay_status , pay_module , pay_controll , pay_action , pay_scene , pay_platform , pay_content , pay_create_time , pay_update_time) VALUES ('rechargeScore' , '2022022016012877780' , 1 , 1 , 23.33 , 1 , 0.12 , 1 , 'user' , 'recharge' , 'score' , 'pc' , 'alipay' , '---' , 1645344088 , 1645344088);
解决方案如下,在不修改thinkphp5原代码的核心内核情况下,我们只需要修改sqlite3连接引擎里面获取数据表字段相关 打开 thinkphp\library\think\db\connector\Sqlite.php 将 ‘type’ => $val[‘type’] 换成 ‘type’ => t h i s − > f i e l d s T y p e ( this->fieldsType( this−>fieldsType(val[‘type’])
/**
* 特殊类型转换为SQLITE常用字段(TP自动绑定时获取的类型)
* @param string $type
* @return string
*/
private function fieldsType($type=''){
if(preg_match('/(int|double|float|decimal|real|numeric|serial|bit)/is', $type)){
return 'TEXT';
}
return $type;
}
最终我们使用getLastSql函数查看最终执行的语句时就正常了。
"INSERT INTO dc_pay (pay_name , pay_sign , pay_info_id , pay_user_id , pay_price , pay_quantity , pay_total_fee , pay_status , pay_module , pay_controll , pay_action , pay_scene , pay_platform , pay_content , pay_create_time , pay_update_time) VALUES ('rechargeScore' , '2022022016075637951' , 1 , 1 , '23.33' , 1 , '0.12' , 1 , 'user' , 'recharge' , 'score' , 'pc' , 'alipay' , '---' , 1645344476 , 1645344476)";