PHP中比较SQL数据库与XLS文件中西里尔字符串相等的问题
你遇到的视觉一致但字符串对比失败的问题,本质是三个常见原因导致:1. 两端编码不统一;2. 字符串包含不可见控制字符;3. 存在同形异义字符(外观相同的拉丁/西里尔字符编码不同)。
排查步骤
1. 确认编码一致性
- 数据库表、存储发件人名称的字段编码必须统一为
utf8mb4,排序规则建议使用utf8mb4_bg_0900_ai_ci适配保加利亚语 - 数据库连接时指定编码为utf8mb4,避免读取数据时出现编码转换错误
- 确认PhpSpreadsheet读取Excel文件时的编码匹配,如果Excel文件是保加利亚语常用的Windows-1251编码,需要显式指定输入编码:
$Reader = new Xlsx(); // 根据实际文件编码调整,常见西里尔文件编码为Windows-1251或UTF-8 $Reader->setInputEncoding('Windows-1251'); $spreadSheet = $Reader->load($targetPath);
2. 排查不可见字符与同形字符
运行以下代码输出两个字符串的字节编码,确认差异点:
function getStrHex($str): string { $hex = []; foreach (str_split($str) as $char) { $hex[] = dechex(ord($char)); } return implode(' ', $hex); } echo '数据库字符串编码:' . getStrHex($name1) . '<br>'; echo 'Excel读取字符串编码:' . getStrHex($name2) . '<br>';
如果出现多余的e2 80 8b(零宽空格)、ef bb bf(BOM头)等字节,就是存在不可见控制字符;如果对应位置的字符字节不同但外观一致,就是同形异义字符。
最终解决代码
先统一清洗两个字符串,再做对比:
// 字符串清洗函数 function cleanCyrillicStr(string $str): string { // 移除首尾空白 $str = trim($str); // 移除零宽空格、BOM头、全角不间断空格等不可见特殊字符 $str = preg_replace('/[\x{200B}-\x{200D}\x{FEFF}\x{A0}]/u', '', $str); // 合并连续空格 $str = preg_replace('/\s+/', ' ', $str); // 同形字符映射:把混在西里尔中的拉丁同形字符转成对应西里尔字符 $translitMap = [ 'A' => 'А', 'B' => 'В', 'C' => 'С', 'E' => 'Е', 'H' => 'Н', 'K' => 'К', 'M' => 'М', 'O' => 'О', 'P' => 'Р', 'T' => 'Т', 'Y' => 'У', 'X' => 'Х', 'a' => 'а', 'o' => 'о', 'p' => 'р', 'c' => 'с', 'x' => 'х' ]; return strtr($str, $translitMap); } // 清洗后对比 $cleanName1 = cleanCyrillicStr($name1); $cleanName2 = cleanCyrillicStr($name2); if (mb_strtolower($cleanName1, 'UTF-8') === mb_strtolower($cleanName2, 'UTF-8')) { // 匹配成功,执行后续文件处理逻辑 }
内容的提问来源于stack exchange,提问作者milenmk
相关产品推荐
相关产品推荐

