gpt4 book ai didi

php - 我的 PHP 应用程序是否正确支持 UTF-8?

转载 作者:IT王子 更新时间:2023-10-29 00:56:21 25 4
gpt4 key购买 nike

我想确保我对 UTF-8 的了解都是正确的。我已经尝试使用 UTF-8 有一段时间了,但我不断遇到越来越多的错误和其他奇怪的事情,这使得拥有 100% UTF-8 站点几乎是不可能的。总有一个我似乎想念的地方。也许这里有人可以更正我的 list 或确定它,这样我就不会错过任何重要的事情。

数据库

每个站点都必须将数据存储在某处。无论您的 PHP 设置是什么,您还必须配置数据库。如果您无法访问配置文件,请确保在连接后立即执行“ SET NAMES 'utf8' ”。另外,请确保使用 utf8_ unicode_ ci在你所有的 table 上。这假设 MySQL 作为一个数据库,你将不得不为其他人改变。

正则表达式

我做了很多正则表达式 more complex比您的平均搜索替换。我必须记住使用“/u”修饰符,以便 PCRE doesn't corrupt my strings .然而,即便如此,仍有still problems apparently .

字符串函数

所有默认字符串函数(strlen()、strpos() 等)都应替换为 Multibyte String Functions查看字符而不是字节。

标题
您应该确保您的服务器为浏览器返回正确的 header ,以了解您尝试使用的字符集(就像您必须告诉 MySQL 一样)。

header('Content-Type: text/html; charset=utf-8');



在页眉中放置正确的 标签也是一个好主意。尽管实际的 header 会在它们不同时覆盖它。
<meta http-equiv="Content-Type" content="text/html;charset=utf-8">

问题

我是否需要在页面加载时将从用户代理(HTML 表单和 URI)收到的所有内容转换为 UTF-8,或者我是否可以将字符串/值保持原样并仍然通过这些函数运行它们而不会出现问题?

如果我确实需要将所有内容都转换为 UTF-8 - 那么我应该采取哪些步骤? mb_detect_encoding似乎是为此而构建的,但我一直看到人们提示它并不总是有效。 mb_check_encoding从格式错误的字符串中分辨出好的 UTF-8 字符串似乎也有问题。

PHP 是否根据它使用的编码(如文件类型)以不同方式在内存中存储字符串,或者它仍然像常规字符串一样存储,其中某些字符的解释方式不同(如 & amp; 与 HTML 中的 &)。 chazomaticus回答这个问题:

In PHP (up to PHP5, anyway), strings are just sequences of bytes. There is no implied or explicit character set associated with them; that's something the programmer must keep track of.



如果将非 UTF-8 字符串提供给 mb_* 函数会导致问题吗?

如果 UTF 字符串编码不正确,会出现问题(例如正则表达式中的解析错误?)还是只会将实体标记为错误(html)?是否有可能不正确编码的字符串会导致函数返回 FALSE,因为字符串是坏的?

我听说您也应该将表单标记为 UTF-8(accept-charset="UTF-8"),但我不确定这样做的好处是什么..?

编写 UTF-16 是为了解决 UTF-8 中的限制吗?就像 UTF-8 字符空间不足? (Y2(UTF)k?)

函数

以下是我发现的几个自定义 PHP 函数,但我没有任何方法来验证它们是否确实有效。也许有人有一个我可以使用的例子。首先是 convertToUTF8()然后来自wordpress的seas_utf8。
function seems_utf8($str) {
$length = strlen($str);
for ($i=0; $i < $length; $i++) {
$c = ord($str[$i]);
if ($c < 0x80) $n = 0; # 0bbbbbbb
elseif (($c & 0xE0) == 0xC0) $n=1; # 110bbbbb
elseif (($c & 0xF0) == 0xE0) $n=2; # 1110bbbb
elseif (($c & 0xF8) == 0xF0) $n=3; # 11110bbb
elseif (($c & 0xFC) == 0xF8) $n=4; # 111110bb
elseif (($c & 0xFE) == 0xFC) $n=5; # 1111110b
else return false; # Does not match any model
for ($j=0; $j<$n; $j++) { # n bytes matching 10bbbbbb follow ?
if ((++$i == $length) || ((ord($str[$i]) & 0xC0) != 0x80))
return false;
}
}
return true;
}

function is_utf8($str) {
$c=0; $b=0;
$bits=0;
$len=strlen($str);
for($i=0; $i<$len; $i++){
$c=ord($str[$i]);
if($c > 128){
if(($c >= 254)) return false;
elseif($c >= 252) $bits=6;
elseif($c >= 248) $bits=5;
elseif($c >= 240) $bits=4;
elseif($c >= 224) $bits=3;
elseif($c >= 192) $bits=2;
else return false;
if(($i+$bits) > $len) return false;
while($bits > 1){
$i++;
$b=ord($str[$i]);
if($b < 128 || $b > 191) return false;
$bits--;
}
}
}
return true;
}

如果有人感兴趣,我找到了一个很好的示例页面来使用 when testing UTf-8 .

最佳答案

Do I need to convert everything that I receive from the user agent (HTML form's & URI) to UTF-8 when the page loads



否。用户代理应以 UTF-8 格式提交数据;否则,您将失去 Unicode 的好处。

确保用户代理以 UTF-8 格式提交的方法是提供包含它以 UTF-8 编码提交的表单的页面。使用 Content-Type header (如果您打算保存表单并独立工作,也可以使用元 http-equiv)。

I have heard that you should mark you forms as UTF-8 also (accept-charset="UTF-8")



别。这在 HTML 标准中是一个不错的主意,但 IE 从来没有把它做对。它应该声明一个允许字符集的排他列表,但 IE 将其视为一个额外的字符集列表,以每个字段为基础进行尝试。因此,如果您有一个 ISO-8859-1 页面和一个“accept-charset="UTF-8"”形式,IE 将首先尝试将一个字段编码为 ISO-8859-1,如果有一个非 8859-1字符在那里,然后它会诉诸UTF-8。

但是由于 IE 没有告诉您它是否使用了 ISO-8859-1 或 UTF-8,所以这对您来说绝对没有用。对于每个字段,您必须分别猜测正在使用哪种编码!没用。省略该属性并将您的页面作为 UTF-8 提供;这是你目前能做的最好的事情。

If a UTF string is improperly encoded will something go wrong



如果您让这样的序列进入浏览器,您可能会遇到麻烦。存在“超长序列”,它们在比所需更长的字节序列中编码低编号的代码点。这意味着如果您通过在字节序列中查找该 ASCII 字符来过滤“<”,您可能会遗漏一个,并将脚本元素放入您认为是安全的文本中。

过长的序列在 Unicode 的早期就被禁止了,但是微软花了很长时间才把它们放在一起:IE 将字节序列 '\xC0\xBC' 解释为 '<' 直到 IE6 Service Pack 1。 Opera 在(我认为)版本 7 之前也出错了。幸运的是,这些较旧的浏览器正在消亡,但仍然值得过滤过长的序列,以防这些浏览器现在仍然存在(或者新的白痴浏览器将来会犯同样的错误) )。您可以这样做,并使用仅允许正确 UTF-8 通过的正则表达式来修复其他错误序列,例如 this one从 W3。

如果您在 PHP 中使用 mb_ 函数,您可能不会遇到这些问题。我不能肯定,因为当我还在编写 PHP 时 mb_* 是无法使用的脆弱的。

在任何情况下,这也是删除控制字符的好时机,这是一个很大且通常不被重视的错误来源。除了 W3 正则表达式删除的其他字符之外,我还会从提交的字符串中删除字符 9 和 13;对于您知道不应该是多行文本框的字符串,删除纯换行符也是值得的。

Was UTF-16 written to address a limit in UTF-8?



不,UTF-16 是每个代码点两个字节的编码,用于使索引 Unicode 字符串在内存中更容易(从所有 Unicode 都适合两个字节的日子开始;像 Windows 和 Java 这样的系统仍然这样做)。与 UTF-8 不同,它与 ASCII 不兼容,并且在 Web 上几乎没有用处。但是你偶尔会在保存的文件中遇到它,通常是由 Windows 用户保存的,这些用户被 Windows 在另存为菜单中将 UTF-16LE 描述为“Unicode”所误导。

seems_utf8



与正则表达式相比,这是非常低效的!

Also, make sure to use utf8_unicode_ci on all of your tables.



您实际上可以在没有这个的情况下逃脱,将 MySQL 视为仅存储字节的存储,并且仅在脚本中将它们解释为 UTF-8。使用 utf8_unicode_ci 的优点是它将整理(排序和不区分大小写的比较)与非 ASCII 字符的知识,例如。 ‘ŕ’和‘Ŕ’是同一个字符。如果您使用非 UTF8 归类,则应坚持使用二进制(区分大小写)匹配。

无论您选择哪种方式,请始终如一:为您的表使用与您为您的连接所做的相同的字符集。您想要避免的是脚本和数据库之间的有损字符集转换。

关于php - 我的 PHP 应用程序是否正确支持 UTF-8?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1317152/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com