PHP导入Unibet XML赔率至数据库仅插入2条:dec2frac函数异常排查
问题排查与修复方案
嘿,从你描述的情况来看,核心问题百分百出在dec2frac函数上——它要么在处理部分十进制赔率时抛出了未捕获的错误,要么返回了数据库不接受的无效值,导致插入流程直接卡壳,只完成了2条记录的插入。移除它后所有投注项都能正常插入,说明函数本身的逻辑或者错误处理有漏洞,咱们一步步来解决:
先定位函数的问题点
首先得搞清楚是哪些赔率值触发了异常,给dec2frac加上错误捕获和日志记录,就能精准定位掉链子的地方:
function dec2frac($decimal) { try { // 保留你原有的函数逻辑 if ($decimal == 0) return "0/1"; $numerator = 1; $denominator = 1; $epsilon = 1e-6; $sign = $decimal < 0 ? -1 : 1; $decimal = abs($decimal); while (abs($decimal - $numerator/$denominator) > $epsilon) { if ($decimal > $numerator/$denominator) { $numerator++; } else { $denominator++; } } return $sign * $numerator . "/" . $denominator; } catch (Exception $e) { // 把错误信息和出问题的赔率值写入日志 error_log("dec2frac处理失败!值为:{$decimal},错误:{$e->getMessage()}"); // 返回数据库能接受的默认值,避免插入流程中断 return "0/1"; } }
另外,你的插入代码可能没处理数据库报错——如果某条记录插入失败,脚本可能直接终止。给插入逻辑也加上错误捕获,保证一条失败不影响其他:
// 假设你用PDO操作数据库 try { $stmt = $pdo->prepare("INSERT INTO your_table (event_id, odds) VALUES (?, ?)"); $stmt->execute([$eventId, $calculatedOdds]); } catch (PDOException $e) { error_log("赛事{$eventId}插入失败!赔率值:{$calculatedOdds},错误:{$e->getMessage()}"); // 跳过这条记录,继续处理下一个赛事 continue; }
优化函数逻辑,避免死循环或无效返回
你原来的dec2frac用循环逼近分数,某些特殊十进制值可能会让循环无限运行(比如无法用简单分数精准表示的数值),导致脚本超时,只完成部分插入。给循环加个最大次数限制:
function dec2frac($decimal) { if ($decimal == 0) return "0/1"; $numerator = 1; $denominator = 1; $epsilon = 1e-6; $sign = $decimal < 0 ? -1 : 1; $decimal = abs($decimal); $maxLoops = 1000; // 防止无限循环 $loopCount = 0; while (abs($decimal - $numerator/$denominator) > $epsilon && $loopCount < $maxLoops) { if ($decimal > $numerator/$denominator) { $numerator++; } else { $denominator++; } $loopCount++; } // 如果达到最大循环次数,返回原十进制的字符串形式兜底 if ($loopCount >= $maxLoops) { error_log("dec2frac处理超时!值为:{$decimal}"); return (string)$decimal; } return $sign * $numerator . "/" . $denominator; }
插入前验证格式合法性
最后,在插入数据库前,先检查dec2frac的返回值是否符合数据库字段要求(比如是不是数字/数字的标准分数格式):
$calculatedOdds = dec2frac($decimalOdds); // 用正则验证分数格式 if (!preg_match('/^-?\d+\/\d+$/', $calculatedOdds)) { error_log("无效的赔率格式!原十进制值:{$decimalOdds},转换后:{$calculatedOdds}"); // 换成数据库能接受的格式,比如直接用原十进制值 $calculatedOdds = (string)$decimalOdds; } // 再执行插入操作
按照上面的步骤来,你既能保留赔率转换的功能,又能保证所有赛事的投注记录都能正常插入数据库啦。
内容的提问来源于stack exchange,提问作者Tipstr
相关产品推荐
相关产品推荐

