我从API导入XML文件。我使用simplexml_load_file()来加载文件。 XML具有UTF-8编码。在一些元素的标题特殊字符accur,如“café”。如果我直接在浏览器中输出这些标题,我看到它们就好了,但我将所有值存储在MySQL数据库中。虽然该表具有UTF-8编码,但值的存储方式类似于“Paardcafé”。 我尝试了不同的enconding,htmlentities等,但输出保持不变。即使编码没有从原始文件更改为存储到数据库中,为什么会出现这种情况?
答案 0 :(得分:1)
编码就像一个链条,如果一个链接断开,整个链断裂。
由于编码是实际数据旁边的元信息,因此使用该数据的不同进程需要具有该元信息。如果一个进程的编码信息错误,则会显示错误的编码。
在您的情况下,您有以下链:
API -> XML -> SimpleXMLElement -> PHP Variable -> Database Link -> Database Store
问题在于最后的部分,对于您已经检查过的API,XML,SimpleXMLElement和PHP变量,编码是正确的。左边是结尾部分:
PHP Variable -> Database Link -> Database Store
*good* *bad*
如您所见,数据库链接介于两者之间。那么那里发生了什么?
数据库链接包含一些信息,其中从PHP传递的编码字符在被提供给数据库存储时被编码。
这是怎么样的?让我们在PHP代码中看到您的问题:
$word = "café";
假设这个PHP代码编码为UTF-8(当浏览器请求答案时,它也会在Stackoverflow上)。在计算机内存中,它存储为二进制数据。这是逐字节的,在这种情况下,如果您查看内存,您会看到类似这样的内容:
636166c3a9
这五个字节代表“café
”字符为UTF-8:
c := 63
a := 61
f := 66
é := c3a9
与内存中的二进制数据一样,它类似于数据库链接如何将字符传输到数据库服务器:作为二进制数据。
所以链接的另一端需要知道如何解释这个二进制序列。为此,它需要知道编码,因为数据库需要将数据存储到您说它是UTF-8编码的列中。
因此,例如,如果数据库服务器通过数据库链接变成二进制字符数据,该数据库链接的编码与列所需的编码不同,则数据库服务器重新生成 - 将通过链接传递的二进制数据编码为将数据存储在列中所需的编码:
link: <data:latin1> -- (re-encode) --> column: <data:utf8>
因此,假设数据库链接具有将字符编码为ISO-8859-1(拉丁语1)的信息,同时它发送二进制序列&lt; 636166c3a9
&gt; ;从上面。该列需要有UTF-8。然后数据库服务器将重新编码该序列:
(latin1) 636166c3a9 ---> (utf8) 636166c383c2a9
然而,对于相同的操作,如果数据库链接将携带数据被编码为UTF-8的信息,则不需要重新编码,因为它已经在列的正确编码中:
(utf8) 636166c3a9 ---> (utf8) 636166c3a9
因此,让我们从最后两个例子中比较可读字符中的二进制UTF-8序列:
636166c383c2a9 := café
636166c3a9 := café
看起来很熟悉?因此,即使PHP代码中的数据具有UTF-8编码和,数据库列的编码也是UTF-8,如果数据库链接携带错误的编码信息,编码仍然可能被破坏。 / p>
那么如何告诉Database Link使用哪种编码?这取决于数据库驱动程序。你正在使用Mysql,所以你可能在PHP中使用PDO。对于PDO Mysql,您可以将 charset 参数添加到DSN,例如最后的“;charset=utf8
”:
$pdo = new PDO("mysql:host=localhost;dbname=world;charset=utf8", "my_user", "my_password");
或者,如果您使用的是Mysqli,请调用set_charset
方法:
$mysqli = new mysqli("localhost", "my_user", "my_password", "world");
$mysqli->set_charset('utf8');
我希望这会让您更清楚这个问题,并向您展示如何更改设置。
答案 1 :(得分:0)
检查从PHP到数据库的连接编码。