You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

迁移至新服务器与PHP7.4时json_decode及unserialize失败排查

问题排查与解决方案

核心原因剖析

问题根源在于PHP 7.4对JSON/序列化数据的校验规则更严格,以及新旧服务器的ODBC驱动字符集处理逻辑差异:

  • PHP 5.5的json_decode和unserialize对ASCII控制字符(0-31、127号)容忍度极高,即使数据包含这类字符也能尝试解码;但PHP 7.4开始遵循严格的JSON规范,这类控制字符会直接触发Unexpected control character found错误。
  • 数据库采用SQL_Latin1_General_CP1_CI_AS排序规则(对应Windows-1252编码),SERVER1的ODBC驱动可能在数据读取时自动过滤了控制字符,而SERVER2的驱动原样返回了这些字符,导致PHP 7.4解码失败。

分步排查与修复

1. 核对ODBC字符集配置

  • 分别查看两台服务器的ODBC数据源管理器(ODBC Data Source Administrator),确认**字符集(Character Set)**配置是否一致,建议统一设置为SQL_Latin1_General_CP1_CI_AS或Windows-1252。
  • 检查PHP数据库连接代码,确保连接字符串中指定了匹配的字符集参数,例如:
    $dsn = "Driver={SQL Server};Server=SERVER2;Database=your_db;CharacterSet=SQL_Latin1_General_CP1_CI_AS";
    $conn = odbc_connect($dsn, $user, $pass);
    

2. 对比原始数据的十六进制输出

在两台服务器上运行以下代码,读取数据库数据并输出十六进制,验证控制字符的存在差异:

$rawData = odbc_result($conn, "your_text_column");
// 输出十六进制字符串,查看是否包含0x00-0x1F或0x7F字符
echo bin2hex($rawData);
  • 若SERVER1的输出无控制字符,说明其驱动自动过滤;若SERVER2存在这类字符,需调整驱动配置或手动处理。

3. 临时兼容修复

如果无法立即调整ODBC配置,可在读取数据后清除控制字符,兼容新旧服务器:

// 仅清除ASCII控制字符,保留正常字符
$cleanData = preg_replace('/[\x00-\x1F\x7F]/u', '', $rawData);
// 执行解码
$jsonData = json_decode($cleanData);
$serializedData = unserialize($cleanData);

/u修饰符确保Unicode字符不会被误过滤,仅针对ASCII控制字符生效。

4. 长期规范方案

  • 将数据库文本字段的排序规则迁移至UTF8MB4_GENERAL_CI,彻底避免字符集转换带来的问题;
  • 在数据写入数据库前提前清除控制字符,从源头杜绝无效数据:
$processedData = preg_replace('/[\x00-\x1F\x7F]/u', '', $originalData);
// 执行写入操作
odbc_exec($conn, "INSERT INTO your_table (your_text_column) VALUES ('$processedData')");

额外验证项

  • 检查SERVER2的PHPmbstring扩展配置,确认mbstring.internal_encoding与数据库字符集匹配;
  • 对比两台服务器的ODBC驱动版本,不同版本的驱动对字符集的处理逻辑可能存在差异。

内容的提问来源于stack exchange,提问作者Dutchie432

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.29 04:14:57