提问人:raphie 提问时间:11/11/2023 最后编辑:raphie 更新时间:11/14/2023 访问量:83
utf8_encode 和 mb_convert_encoding 冲突的 Resuts [复制]
utf8_encode and mb_convert_encoding Conflicting Resuts [duplicate]
问:
在将数据从 PHP(使用 )传输到 MySQL 时,我遇到了一个非常烦人的问题,在 web.config 设置为的 IIS 环境中:default_charset = 'UTF-8'
<globalization requestEncoding="UTF-8" responseEncoding="UTF-8" />
还在具有相同默认字符集的 Apache 环境中进行了测试,结果相同。我还将MySQLi设置为在任何查询之前设置charset:
$mysqli->set_charset('UTF-8');
我还有一组准备好的语句,用于搜索字符串中的每个字符,以使用以下命令将任何无 UTF-8 编码转换为 UTF-8:
mb_convert_encoding($char, 'UTF-8', mb_detect_encoding($char));
在尝试使用相同的过程解析整个字符串并失败后:
mb_convert_encoding($string, 'UTF-8', mb_detect_encoding($string));
带有脚本的文件的内容类型在标头上设置为内容类型字符集 UTF-8
。但这些仍然没有解决问题。
我还将MySQL表和模式的所有排序规则设置为,当然还要使用'utf8mb4_unicode_520_ci'。尽管如此,问题仍然存在。utf8mb4
我编写的用于拆分字符串的函数如下:
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_convert_encoding没有完成它的工作。mb_detect_encoding
如果有人能帮忙,我将不胜感激。我一直在寻找解决方案,但提供的解决方案都没有奏效。我发现自己陷入了困境,因为有效的方法已被弃用。
所以,这些是我面临的问题列表:
- mb_convert_encoding -> 未编码或编码为 UTF8 以外的内容
- mb_detect_encoding -> 未正确检测
- 字符串编码为 ASCII,而不是 UTF-8 作为请求标头中的字符集。
- 混淆:为什么我需要将 UTF-8 编码字符编码为 UTF-8 才能工作?
答:
在寻找答案和一整天的研究之后,这就是问题所在。过度处理。在开发过程中的某个时候,中间件被放置到位,以验证每个 POST/GET 请求并处理每个值,以确保发送的编码是 UTF-8。我正在重构的代码已经负责处理数据。
中间件是使用 编码的,因此,我怀疑函数检查本身以避免过度处理。我还必须重构中间人,这样就不会发生冲突。utf8_encode
所以,这就是问题所在,两个不同的代码正在处理产生冲突的编码。一旦我重构了中间件,问题就停止了。
总之,问题不在于 或者,如果您有类似的问题,请确保您正在处理的代码没有使用两种不同的方法执行具有不同功能的类似过程。mb_convert_encoding
mb_detect_encoding
就我而言,中间件没有验证或设置为检测字符串是否已编码为 UTF-8,它只是无论如何都实现了编码。这也是我因重构代码而获得报酬的原因。
对我来说仍然没有意义的是为什么正确的 UTF-8 编码字符串会导致 MySQL 抛出错误。为此,我怀疑过度处理正在损坏输入。
ED
是 的 拉丁 1 编码。您应该找到 latin1 中的编码内容,然后将其更改为 use(又名 MySQL's )或告诉 MySQL 您的数据在 并让它在存储 () 和检索 () 时进行转换。í
UTF-8
CHARACTER SET = utf8mb4
CHARACTER SET latin1
INSERTs
SELECTs
不要使用任何转换例程 (mb_*),这往往会使混乱变得更糟。
acute-i 的 UTF-8 (utf8mb4) 编码为 .C3AD
有关更多讨论,请参阅Trouble with UTF-8 characters中的“black diamond”;我看到的不是我存储的
评论
mb_convert_encoding()
mb_detect_encoding()
str_split()
utf8_encode()
严格从 ISO-8859-1 转换为 UTF-8。 如果没有可选的第 3 个参数,则指定源编码将使用 PHP 配置中当前配置的默认编码。因此,如果前者有效,但后者无效,则配置的默认编码可能与输入字符串不匹配,您应该显式定义输入编码。此外,无法可靠地检测文本编码,并且声称这样做的函数是猜测。文本编码是您必须始终注意的元数据。mb_convert_encoding()