这里有一些非常好的答案,并尝试回答您的问题。我不是编码大师,但是我了解您希望拥有一个纯 UTF-8堆栈一直到您的数据库的愿望。我一直在使用MySQL的utf8mb4
表,字段和连接编码。
我的情况归结为“当数据来自HTML表单或电子邮件注册链接时,我只想让我的消毒器,验证器,业务逻辑和准备好的语句处理UTF-8”。因此,我以一种简单的方式开始了这个想法:
- 尝试检测编码:
$encodings = ['UTF-8', 'ISO-8859-1', 'ASCII'];
- 如果无法检测到编码,
throw new RuntimeException
- 如果输入为
UTF-8
,继续。
否则,如果是ISO-8859-1
或ASCII
一个。尝试转换为UTF-8(等待,未完成)
b。检测转换值的编码
C。如果报告的编码和转换后的值均为UTF-8
,则继续。
d。其他,throw new RuntimeException
从我的抽象课 Sanitizer
private function isUTF8($encoding, $value)
{
return (($encoding === 'UTF-8') && (utf8_encode(utf8_decode($value)) === $value));
}
private function utf8tify(&$value)
{
$encodings = ['UTF-8', 'ISO-8859-1', 'ASCII'];
mb_internal_encoding('UTF-8');
mb_substitute_character(0xfffd); //REPLACEMENT CHARACTER
mb_detect_order($encodings);
$stringEncoding = mb_detect_encoding($value, $encodings, true);
if (!$stringEncoding) {
$value = null;
throw new \RuntimeException("Unable to identify character encoding in sanitizer.");
}
if ($this->isUTF8($stringEncoding, $value)) {
return;
} else {
$value = mb_convert_encoding($value, 'UTF-8', $stringEncoding);
$stringEncoding = mb_detect_encoding($value, $encodings, true);
if ($this->isUTF8($stringEncoding, $value)) {
return;
} else {
$value = null;
throw new \RuntimeException("Unable to convert character encoding from ISO-8859-1, or ASCII, to UTF-8 in Sanitizer.");
}
}
return;
}
有人可能会提出一个论点,即我应该将编码问题与抽象Sanitizer
类分开,然后将一个Encoder
对象简单地注入到的具体子实例中Sanitizer
。但是,我的方法的主要问题是,在没有更多知识的情况下,我只是拒绝了不需要的编码类型(并且我依赖于PHP mb_ *函数)。没有进一步的研究,我不知道这是否会伤害某些人群(或者,如果我在重要信息上迷失了方向)。所以,我需要了解更多。我找到了这篇文章。
每个程序员绝对肯定要了解与文本一起使用的编码和字符集的知识
此外,将加密数据添加到我的电子邮件注册链接(使用OpenSSL
或mcrypt
)时会发生什么?这会干扰解码吗?Windows-1252呢?那么安全隐患呢?utf8_decode()
和utf8_encode()
in 的使用Sanitizer::isUTF8
令人怀疑。
人们指出了PHP mb_ *函数的缺点。我从未花时间进行调查iconv
,但是如果它比mb_ * functions更好,请告诉我。