PHP花括号引号字符编码问题
PHP花括号引号字符编码问题
我知道不同字符集之间存在着一个古老的字符编码问题,但我卡在了与Windows的“弯引号”相关的问题上。\n我们有一个客户喜欢将数据复制粘贴到文本字段中,然后将其发布到我们的应用程序上。这些数据通常会包含弯引号。我过去常用以下代码将它们转换为正常的引号:\n
function convert_smart_quotes($string) { $badwordchars=array("\xe2\x80\x98", "\xe2\x80\x99", "\xe2\x80\x9c", "\xe2\x80\x9d", "\xe2\x80\x93", "\xe2\x80\x94", "\xe2\x80\xa6"); $fixedwordchars=array("'", "'", '"', '"', '-', '--', '...'); return str_replace($badwordchars,$fixedwordchars,$string); }
\n这个方法在前几个月非常有效。然而,在一些更改之后(我们切换了服务器,对系统进行了更新,升级了PHP等等),我们发现这个方法不再起作用。因此,我进行了检查,发现“弯引号”都变成了其他字符。在这种情况下,它们变成了以下字符:\n“ = ¡È\n” = ¡É\n‘ = ¡Æ\n’ = ¡Ç\n这些字符在保存到数据库中时会显示为被诅咒的“黑色菱形问号符号”。我的MySQL数据库和应用程序都是使用latin1_swedish_ci编码的。因此,尽管我知道utf-8更好,但它必须保持为latin1_swedish_ci或ISO-8859-1,否则我们将不得不重新构建所有内容……这是不可能的。\n我的网页和表单都是以utf-8编码进行提交的。如果我将其更改为ISO-8859-1,引号就会变成问号。\n我尝试搜索字符串中出现的“¡È”或“¡É”,并将其替换为正常引号,但我无法使其起作用。我在上面的函数中添加了以下代码来实现:\n
$string = str_replace("xa1\xc8", '"', $string); $string = str_replace("xa1\xc9", '"', $string); $string = str_replace("xa1\xc6", "'", $string); $string = str_replace("xa1\xc7", "'", $string);
\n我已经卡在这个问题上几个小时了,但在网上没有找到真正有用的帮助。如您所想象的那样,谷歌搜索“¡É”并没有带来非常具体的回应。\n感谢您的指导!
PHP中的花括号引号字符编码问题
在PHP中,有时在使用花括号引号(curly quote)时会遇到编码问题。为了解决这个问题,可以使用以下代码:
$str = mb_convert_encoding($str, 'HTML-ENTITIES', 'UTF-8');
或者
$str = mb_convert_encoding($str, 'HTML-ENTITIES', 'auto');
更多信息可以在PHP文档网站上找到。这是我个人遇到的最简单的解决方法。这个答案没有提供一个指向"更多信息可以在PHP文档网站上找到"的链接,所以[这是链接](https://www.php.net/manual/en/mbstring.supported-encodings.php)。引用一句话:在"mbstring模块支持的字符编码中",有一个叫做"HTML-ENTITIES"(别名:"HTML")的编码。
以上是解决PHP中花括号引号字符编码问题的方法。
问题原因:问题出现的原因是你从用户那里接受了UTF-8编码的输入,然后将其插入到数据库中,但是把它当作Latin1(ISO-8859-1)编码处理。注意,latin1_swedish_ci
不是一个编码,而是一个排序规则(用于Latin1)。为了解决字符编码问题,排序规则并不重要。
解决方法:不要手动识别重要的UTF-8序列并替换它们,而是应该使用一种强大的方法将UTF-8字符串转换为Latin1,比如使用iconv
函数。
需要注意的是,这是一种有损转换:一些UTF-8字符,比如花引号,在Latin1中是不存在的。你可以选择忽略这些字符(将它们替换为空字符串、?或其他内容),或者选择将它们转换为近似的字符(比如用"
替换花引号)。但如果有人在你的表单中输入了金
,你该怎么处理呢?
iconv
函数将尽可能进行近似转换:
// 将UTF-8转换为Latin1,尽可能使用最接近的Latin1字符进行替换(//TRANSLIT) $latinString = iconv("UTF-8", "ISO-8859-1//TRANSLIT", $utf8String);
(你还可以配置它忽略所有超出范围的字符——请参阅iconv
的文档以获取更多信息。)
如果你不想麻烦地添加一个新的库,PHP也自带了utf_decode
函数:
$latinString = utf_decode($utf8String);
然而,PHP并不是为处理多个字符编码而设计的,所以我更喜欢避免使用(有时有bug的)标准库函数来处理编码问题。
你还应该考虑阅读一下《The Absolute Minimum Every Software Developer Absolutely, Positively Must Know About Unicode and Character Sets (No Excuses!)》这篇文章。
对于回复的延迟,我向你道歉。这件事发生后的两天,我辞掉了工作,再也不用处理这个公司或这个问题了。谢谢你详细的回复 🙂