我认为在多语言应用程序的后端使用Unicode编码,前端使用代码页没有任何意义。你要么在整个项目中使用相同的编码方式,要么手动在
UTF-8
和
windows-1252
之间进行转换。
我认为你并没有阅读问题。标签被截断来自数据库,否则您的浏览器将显示垃圾字符。因此,这不是PHP/HTML的问题,而是MySQL的问题。对于
èéàòì
等情况,MySQL当然可以从UTF-8转换为CP1252(latin1)。但是,如果不是这种情况(例如我们尝试将相同的字符串从UTF-8转换为CP1251),MySQL将显示问号
?
。
在您的情况下,我认为这是一个输入问题,即标签在数据库中被截断。这怎么可能?您的PHP和MySQL可能是UTF8,但是当您的浏览器以这样的字符集从加载了该字符集的页面提交表单时,它会发送
windows-1252
字符串。在您的PHP脚本中,您应该在将其插入数据库之前将此字符串转换为
UTF-8
,或者使用
SET NAMES 'CP1252'
连接到MySQL。由于您没有这样做,因此您最终尝试插入一堆无效的UTF-8字节,因此MySQL截断字符串,您的标签为空。这里附上一个测试用例。以下是
test
表格。
CREATE TABLE `test` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(128) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8
这里是PHP部分。请注意,此脚本采用UTF-8编码,因此其中出现的每个文本字符串都具有相同的编码。
$label = "Référence";
$src = mb_convert_encoding($label, "CP1252", "UTF-8");
$db = new PDO('mysql:host=localhost;dbname=test;charset=utf8',
'test', 'test');
$stmt = $db->prepare('INSERT INTO test (name) VALUES ( ? )');
$stmt->bindValue(1, $src);
$stmt->execute();
header("content-type: text/plain; charset=windows-1252");
foreach($db->query('SELECT * FROM test') as $row)
echo $row['name'] . "\n";
你如何进行恢复?你可以使用
cp1252
字符集连接MySQL并让MySQL为你翻译,或者在你的脚本中转换字符串。在正确获取数据后,你需要提取它们并将其放在HTML页面上。这时你会遇到同样的问题,但是相反:在CP1252文档中显示UTF-8字符串。数据库中的字节不适用,因为UTF-8是一种可变长度编码,而在CP1252中,一个字符恰好为1个字节长。如果你直接将这些字节放入页面中,浏览器将会显示一些随机的乱码。因此,你要么连接到指定
CP1252
字符集的数据库,使MySQL负责转换并给你正确的字节,要么在PHP端自己转换字节。或者你最好自己做一个决定:在所有地方使用相同的编码方式。我建议使用
UTF-8
,因为今天这是正确的做法,但你也可以选择
CP1252
,因为它可以表示英语和法语字符(并且节省一些存储空间,但我认为这不是一个问题)。
strlen
而不是mb_strlen
)。 - martinstoeckli