在 web.config
设置为IIS 环境中,将数据从 PHP(使用
default_charset = 'UTF-8'
设置)传输到 MySQL 时,我遇到了一个非常烦人的问题:
<globalization requestEncoding="UTF-8" responseEncoding="UTF-8" />
还在具有相同默认字符集的 Apache 环境中进行了测试,结果相同。我还设置了 MySQLi 在任何查询之前设置字符集:
$mysqli->set_charset('UTF-8');
我还有一组准备好的语句,用于搜索字符串中的each字符,以使用以下方法将任何非 UTF-8 编码转换为 UTF-8:
mb_convert_encoding($char, 'UTF-8', mb_detect_encoding($char));
在尝试失败后,通过使用相同的过程解析整个字符串:
mb_convert_encoding($string, 'UTF-8', mb_detect_encoding($string));
带有脚本的文件的内容类型设置为标题上的 content-type charset UTF-8
已将 MySQL 表和模式的所有排序规则设置为 utf8mb4
,当然还使用“utf8mb4_unicode_520_ci”。尽管如此,问题仍然存在。我写的分割字符串的函数如下:
static private function split_and_convert($value, $encoding = 'UTF-8') {
$split = mb_str_split($value);
$filter = [];
foreach($split as $chr) {
$from = mb_detect_encoding($chr);
$encoded = ($from !== $encoding)
? mb_convert_encoding($chr, $encoding, $from)
: $chr;
$filter[] = $encoded;
// echoing for testing
echo 'char ' . $encoded . ' (' . $from . ')<br>';
}
return join('', $filter);
}
这回显了以下尝试保存的内容Martínez
:
char M (ASCII)
char a (ASCII)
char r (ASCII)
char t (ASCII)
char � (UTF-8)
char n (ASCII)
char e (ASCII)
char z (ASCII)
MySQL 抛出以下错误:
Error No: 1366 - Incorrect string value: '\xEDnez' for column 'contactLast' at row 1
还是没有喜悦。但如果我这样做,它就像一个魅力:
static private function split_and_convert($value, $encoding = 'UTF-8') {
$split = mb_str_split($value);
$filter = [];
foreach($split as $chr) {
$from = mb_detect_encoding($chr);
$encoded = ($from !== $encoding)
? mb_convert_encoding($chr, $encoding, $from)
// set to actually encode the 'UTF-8' encoded char
// I'm supposed not to do this, but is what works
// which makes no sense
: utf8_encode($chr);
$filter[] = $encoded;
// echoing for testing
echo 'char ' . $encoded . ' (' . $from . ')<br>';
}
return join('', $filter);
}
结果如下:
char M (ASCII)
char a (ASCII)
char r (ASCII)
char t (ASCII)
char í (UTF-8)
char n (ASCII)
char e (ASCII)
char z (ASCII)
MySQL 不会抛出任何错误。如果我将 utf8_encode
替换为
mb_convert_encoding($encoded, 'UTF-8')
,我会得到与不过滤字符串相同的错误。我怀疑
mb_detect_encoding
要么错误地检测到字符编码,要么只是 mb_convert_encoding 没有完成它的工作。如果有人可以提供帮助,我将不胜感激。我花了几个小时寻找解决方案,但所提供的解决方案都不起作用。我发现自己陷入了困境,因为有效的方法已被弃用。
所以,这些是我面临的问题列表:
中间人是使用
utf8_encode
进行编码的,所以,我怀疑函数检查本身是为了避免过度处理。我还必须重构中间人,这样就不会有冲突。所以,这就是问题所在,两个不同的代码正在处理编码,从而产生了冲突。一旦我重构了中间人,问题就消失了。
总之,问题不是
mb_convert_encoding
或
mb_detect_encoding
,如果您有类似的问题,请确保您正在处理的代码没有使用两种不同的方法使用不同的功能执行类似的过程。在我的例子中,中间人没有验证或设置为检测字符串是否已经编码为 UTF-8,它只是实现编码。这也是我获得报酬来重构代码的原因。
对于我来说,为什么正确的 UTF-8 编码字符串会导致 MySQL 抛出错误,这仍然是没有意义的。为此,我怀疑过度处理正在破坏输入。