PHP JSON编码UTF8字符问题(MySQL)

16

我正使用 jQuery 的 json_encode 方法,将表单中的数据写入数据库。

然而,从数据库中读取的数据会出现错误。

$db->query("SET NAMES utf8");

$kelime = array("Merhaba","Dünya");
$bilgi = json_encode($kelime);

$incelemeEkle = "
INSERT INTO incelemeRapor SET
bigData = '".$bilgi."'
";
$db->query($incelemeEkle);

数据库表结构;

CREATE TABLE `incelemeRapor` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `bigData` text COLLATE utf8_unicode_ci,
  PRIMARY KEY (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=2 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

MySQL插入示例数据;

["Merhaba","Du00fcnya"]

实际的PHP文件保存为哪种编码? - Matt Gibson
根据MySQL文档,使用SET NAMES时字符集应该用引号括起来,但是你似乎没有这样做,所以你可能没有真正设置utf8。 - Jamie Taniguchi
@Jamie Taniguchi:不,它可以像这样使用。 - Tomas
5个回答

26

在将数据放入SQL查询之前,请始终对其进行转义:

$incelemeEkle = "
INSERT INTO incelemeRapor SET
bigData = '".mysql_real_escape_string($bilgi)."'
";

(添加了mysql_real_escape_string()调用)

json_encode()将非ASCII字符编码为\u<code-point>表示法; 因此,json_encode(array("Merhaba","Dünya"));返回["Merhaba","D\u00fcnya"].

接下来,该字符串嵌入到SQL查询中:

INSERT INTO incelemeRapor SET
bigData = '["Merhaba","D\u00fcnya"]'

在MySQL中,转义序列\u没有特殊含义,因此MySQL会删除掉\,导致["Merhaba","Du00fcnya"]被存储在数据库中。

因此,如果你转义了字符串,查询将变为:

$incelemeEkle = "
INSERT INTO incelemeRapor SET
bigData = '["Merhaba","D\\u00fcnya"]'
";

数据库中存储了["Merhaba","D\u00fcnya"].


2
我尝试使用mysql_real_escape_string(),但对我没有用(导致数据库中的字段为空)。
所以我在这里查看:http://php.net/manual/fr/json.constants.php,并且标记JSON_UNESCAPED_UNICODE对我很好用:
$json_data = json_encode($data,JSON_UNESCAPED_UNICODE);

JSON_UNESCAPED_UNICODE 仅在 PHP 5.4.0 及以上版本可用!


1

因此,除了确保您的数据库使用utf8_unicode_ci之外,您还希望确保PHP使用正确的编码。通常,我会在可能包含外国字符的任何函数的顶部运行以下两个命令。更好的方法是在应用程序启动时将其作为第一个命令运行:

mb_language('uni');
mb_internal_encoding('UTF-8');

这两行代码让我省去了很多麻烦!


0

就像user576875所说的那样,您只需要在将字符串插入数据库之前正确处理它。 mysql_real_escape_string()是一种方法。准备好的语句是另一种方法。这也将使您免受SQL注入安全问题的影响,如果您直接将用户输入写入SQL,则可能会受到影响。始终使用上述两种方法之一。

此外,请注意,这与UTF8关系不大。 JSON是ASCII安全的,因此只要使用类似ASCII的字符集(utf8,iso-8859-1),数据就会被正确插入和存储。


-1

我会对JSON字符串应用BASE64编码。这个方法几乎适用于所有的php设置、数据库、数据库版本和设置:

$values = array("Test" => 1, "the" => 2, "West" => 3);
$encoded = base64_encode(json_encode($values));
$decoded = json_decode(base64_decode($encoded), true);

你不需要将JSON进行base64编码。它是ASCII安全的,只包含7位字符。 - bluesmoon
你说得对。但是Base64编码可以避免反斜杠(或其他特殊字符)带来的任何问题。 - Joe Scylla

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接