thinkphp 读取mysql数据库中tinyint和int 类型的数据 却是string类型

本文介绍了如何解决ThinkPHP框架中PDO连接参数导致的问题。通过修改ThinkPHP/Library/Think/Db/Driver.class.php文件中的$options属性,加入PDO::ATTR_EMULATE_PREPARES => false这一配置项,可以有效解决连接异常的情况。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

网上查询了一下发现是TP默认的PDO连接参数的缘故。

找到TP中的ThinkPHP/Library/Think/Db/Driver.class.php文件,

  1. // PDO连接参数
  2.     protected $options = array(
  3.         PDO::ATTR_CASE              =>  PDO::CASE_LOWER,
  4.         PDO::ATTR_ERRMODE           =>  PDO::ERRMODE_EXCEPTION,
  5.         PDO::ATTR_ORACLE_NULLS      =>  PDO::NULL_NATURAL,
  6.         PDO::ATTR_STRINGIFY_FETCHES =>  false,
  7.         PDO::ATTR_EMULATE_PREPARES  =>   false,  //把这行加上去就可以了,
  8.     );
public function importGoodsDetail(): Json { set_time_limit(0); ini_set('memory_limit', '2048M'); $params = $this->request->param(); if (empty($params["file"])) { return $this->fail('请上传要导入的文件',[],0,1); } $titleArr = [ "物流履约单号" => "logistics_order_no", "货品名称" => "product_name", "货品ID" => "product_id", "货品件数" => "quantity", "货品重量(克)" => "weight", "货品长度(毫米)" => "length", "货品宽度(毫米)" => "width", "货品高度(毫米)" => "height", "货品体积(立方毫米)" => "volume", ]; try { // 使用生成器获取数据流 $dataGenerator = $this->importExeclGenerator($params['file']); $batchSize = 3000; // 每批处理300条,可根据服务器性能调整 $model = new GoodsDetailModel(); $total = 0; $success = 0; $failedBatches = []; // 记录失败的批次 // 直接处理数据,不要使用事务 $batchData = []; foreach ($dataGenerator as $rowData) { $total++; // 转换数据格式 $item = []; foreach ($rowData as $k => $val) { if ($k && $val && isset($titleArr[$k])) { $item[$titleArr[$k]] = trim($val); } } if (!empty($item)) { $batchData[] = $item; } // 达到批次大小或处理完所有数据时插入数据库 if (count($batchData) >= $batchSize) { if (!empty($batchData)) { try { $model->saveAll($batchData); $success += count($batchData); } catch (\Exception $e) { // 记录失败批次(可选) $failedBatches[] = [ 'startRow' => $total - count($batchData) + 1, 'endRow' => $total, 'error' => $e->getMessage() ]; } } $batchData = []; // 清空批次数据 } } // 处理剩余数据 if (!empty($batchData)) { try { //TODO:有优化的空间 速度可以大大提升 赶进度暂且这样... $model->saveAll($batchData); $success += count($batchData); } catch (\Exception $e) { $failedBatches[] = [ 'startRow' => $total - count($batchData) + 1, 'endRow' => $total, 'error' => $e->getMessage() ]; } } // 构建返回结果 $resultMsg = "导入成功,共{$total}条数据,成功导入{$success}条"; if (!empty($failedBatches)) { $resultMsg .= ",失败 ".$total - $success." 条,具体报错信息:".$e->getMessage(); return $this->fail('导入失败',['remark' => $resultMsg],1,1); } return $this->success('导入成功',['remark' => $resultMsg],1,1); } catch (\Exception $e) { return $this->fail('导入失败',['remark' => $e->getMessage()],1,1); } } 上面这是我的php后端用于导入文件,其中调用导入的方法如下: private function importExeclGenerator(string $file_name): \Generator { try { $path = app()->getRootPath() . "public/" . $file_name; $reader = IOFactory::createReaderForFile($path); $reader->setReadDataOnly(true); $spreadsheet = $reader->load($path); // 获取第一个工作表 $sheet = $spreadsheet->getSheet(0); // 获取表头 $title = $sheet->rangeToArray('A1:' . $sheet->getHighestColumn() . '1', null, true, true, true)[1]; if (empty($title)) { throw new \Exception('Excel表头为空'); } $highestRow = $sheet->getHighestRow(); // 逐行生成数据,不一次性加载到内存 for ($row = 2; $row <= $highestRow; $row++) { $rowData = $sheet->rangeToArray( 'A' . $row . ':' . $sheet->getHighestColumn() . $row, null, true, true, true )[$row]; $item = []; foreach ($rowData as $colIndex => $value) { $colName = $title[$colIndex]; if ($colName) { //$item[$colName] = trim($value); $item[$colName] = $value; } } // 使用yield关键字逐行返回数据 yield $item; } } catch (\Exception $e) { throw $e; } } 我是使用了流的形式导入,但是报错502网关超时,我的前端代码如下: //菜鸟仓储费--正向配送费--货品明细导入api export function importGoodsDetail(params:any) { return request.post({ url:'/wareHousFee.newFie.forwardDeliveryFee.GoodsDetail/importGoodsDetail', params, // 我们的标准是100万数据导出 设置超时时间为5小时 (5 * 60 * 60 * 1000 = 18,000,000毫秒) timeout:18000000 }) } <template> <el-dialog :title="upload.title" v-model="show" width="400px"> <el-upload ref="uploadRefs" :limit="1" accept=".xlsx, .xls" :timeout="120000" :max-size="200*1024*1024" :headers="upload.headers" :action="upload.url" :on-progress="handleFileUploadProgress" :on-success="handleFileSuccess" :auto-upload="true" :on-error="uploadErr" drag> <i class="el-icon-upload"></i> <div class="el-upload__text">将文件拖到此处,或点击上传</div> <div class="el-upload__tip text-center" slot="tip"> <span>仅允许导入xls、xlsx格式文件。</span> <!-- <el-link type="primary" :underline="false" style="font-size: 12px; vertical-align: baseline" v-hasPermi="['teacher:import:muban']" @click="importTemplate">下载模板</el-link> --> </div> </el-upload> <div slot="footer" class="dialog-footer"> <el-button type="primary" @click="submitFileForm" :disabled="submitLoading">确 定</el-button> <el-button @click="handleClose">取 消</el-button> </div> </el-dialog> </template> <script lang="ts" setup > import { getToken } from '@/utils/auth' import feedback from '@/utils/feedback' import config from '@/config' import type { ElUpload } from 'element-plus' import { importGoodsDetail } from '@/api/wareHousFee/newBie' import { useRoute } from 'vue-router' const emit = defineEmits(['success']) const route = useRoute() const show = ref(false); const uploadRefs = shallowRef<InstanceType<typeof ElUpload>>() const upload: any = ref({ title: "正向配送费货品明细导入", open: false, url: ref(`${config.baseUrl}${config.urlPrefix}/upload/excel`), headers: { token: getToken(), version: config.version } }); const fileUrl=ref(""); var source= route.query.source; // 控制按钮加载状态 const submitLoading = ref(false); //下载导入模版 未使用 const importTemplate = async () => {} //文件上传进度的回调函数 const handleFileUploadProgress = async (response: any, file: any, fileLists: any[]) => {} //文件上传成功的回调函数 const handleFileSuccess = async (response: any, file: any, fileLists: any[]) => { fileUrl.value=response.data.url } //文件上传失败的回调函数 // 文件上传失败的回调函数 const uploadErr = (error: any, file: any, fileList: any[]) => { console.log('[上传失败] 错误触发'); // 区分不同类型的错误 if (error instanceof Error) { console.log('[上传失败] 错误对象:', error); console.log('[上传失败] 错误信息:', error.message); } else { console.log('[上传失败] 响应数据:', error); // 尝试解析可能的HTTP状态码 if (error.response && error.response.status) { console.log('[上传失败] 状态码:', error.response.status); console.log('[上传失败] 状态文本:', error.response.statusText); } } console.log('[上传失败] 文件信息:', { name: file.name, size: `${(file.size / 1024 / 1024).toFixed(2)}MB`, type: file.type }); } //上传组件确定按钮操作 const submitFileForm = async () => { //防止重复点击确定按钮 if (submitLoading.value) return; feedback.loading('正在导入中...') try { //设置确定按钮禁用 submitLoading.value = true; // 调用后端接口并获取返回结果 const response = await importGoodsDetail({ file: fileUrl.value }); feedback.closeLoading() // 控制台打印返回结果(便于调试) console.log("接口返回结果:", response); emit("success"); show.value = false; } catch (error) { // 接口调用异常(如网络错误、超时等) //console.error("接口调用异常:", error); feedback.msgError("导入失败,接口调用异常,请稍后再试"); feedback.closeLoading() } finally { //无论成功或者失败都设置按钮可点击 submitLoading.value = false; feedback.closeLoading() } } //点击弹窗关闭按钮 const handleClose = () => { fileUrl.value = '' show.value = false } //点击按钮除非open事件打开弹窗 const open = (source:any) => { show.value = true } //defineExpose({ open }) 的核心作用是将子组件的 open 方法显式暴露给父组件 defineExpose({ open }) </script> 请帮我具体排查一下接口是不是写的有问题啊
最新发布
07-06
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值