mysqli没有将字符集设置为utf8mb4

时间:2016-04-27 15:47:07

标签: php mysql encoding utf-8 utf8mb4

发现问题

问题似乎是$mysqli->set_charset()不接受`utf8mb4'作为有效编码(正如我在第一次更新中“推测”的那样)。 MySQL版本是5.5.41,PHP版本是5.4.41(没问题)。

对不起标题,我一直在搜索/阅读问题是什么/在哪里,我已经对此感到困惑......

我最近开始在mysql中使用utf8mb4。我使用utf8mb4作为字符集,使用utf8mb4_unicode_ci作为所有表/列的校对。

所以我先改变了一下:

$mysqli->set_charset('utf8');

$mysqli->set_charset('utf8mb4');

确保我的php文件是utf8(我使用Visual Studio Code,因此文件默认以UTF-8创建),php / html标头设置为utf8:

的index.php

header('Content-type: Text/HTML; Charset=UTF-8');

main.php(包含在index.php的末尾)

<meta http-equiv="Content-Type" content="Text/HTML" />
<meta charset="UTF-8" />

问题是对于某些表我必须手动插入数据,并且这些数据按原样存储:带有特殊字符,带重音符号,等等...当我在我的网站上显示这些数据时我可以看到这些字符已经替换了特殊/重音字符。

所以我的问题是:有没有办法在mysql中存储数据(不替换/转换特殊/重音字符)并能够正常显示(按原样)?

如果我恢复到$mysqli->set_charset('utf8');数据显示正常......所以这让我想知道存储utf-8字符应该没有问题,并且某处存在编码问题......

我正在使用sqlyog社区(带葡萄酒)我在某处读到有时gui在你改变一些数据库/表配置时无法正常工作,唯一的方法是旧方法(自己运行查询) ,但我还没试过呢。我运行查询来设置所有表/列的字符集和排序规则。

您怎么看?

更新

我开始认为mysqli不接受utf8mb4作为有效的字符编码并且使用来自php的utf8而不是来自mysql ...我也认为mysql fckd创建utf8mb4而不是更新现有的utf8以支持4个字节....

当我使用mysqli charset utf8进行测试时,所有内容都按原样存储并按原样显示(将mysql charset和collat​​ion设置为utf8mb4 ...)。

更新2

SELECT name, HEX(name) FROM person LIMIT 1

这是它输出的内容:

New Person has name Altaïr 416C7461C3AF72

但正如我已经说过的,这是在使用:

$mysqli->set_charset('utf8');

插入并选择。如果我使用utf8mb4而不是它存储的内容:

Altaïr

但它显示确定。如果名称按原样存储,显示的名称将为Alta�r

所以问题是:为什么mysqli / mysql使用utf8mb4将ï存储为ï?当在mysqli中设置utf8mb4时,为什么php会将ï等特殊字符显示为

有人可以确认mysqli::set_charset接受utf8mb4作为有效编码吗?

更新3

我有一个类函数,它从表“es”中选择一个字符串,例如:Iniciar Sesión(这是存储的内容),如果mysqli charset是utf8,则选择/显示的是{{1 }}

这可能是一个完全不同的问题,但这显然是另一个编纂问题。根据我的理解,如果表/列是utf8mb4并且mysqli设置为utf8,则mysql必须从utf8(3bytes)编码为ut8mb4(全字节支持)。所以这意味着Iniciar Sesión不使用php中的utf8,而是使用mysql。这是对的吗?

我的应用程序目前编码时间很短......(但可能是某些服务器配置问题...)

更新4

问题可以在这里吗?我真的不知道这种配置:

mysqli

更新4-1 / 2 (从评论中复制)

SHOW VARIABLES WHERE Variable_name LIKE 'character\_set\_%' OR Variable_name LIKE 'collation%';
+--------------------------+--------------------+
| Variable_name            | Value              |
+--------------------------+--------------------+
| character_set_client     | utf8               |
| character_set_connection | utf8               |
| character_set_database   | utf8mb4            |
| character_set_filesystem | binary             |
| character_set_results    | utf8               |
| character_set_server     | latin1             |
| character_set_system     | utf8               |
| collation_connection     | utf8_general_ci    |
| collation_database       | utf8mb4_unicode_ci |
| collation_server         | latin1_swedish_ci  |
+--------------------------+--------------------+
10 rows in set (0.00 sec)

3 个答案:

答案 0 :(得分:1)

问题可能源于您在MySQL列定义中没有使用utf8mb4这一事实(至少您没有说明您正在使用的编码)。

以下是MySQL表定义的示例,其中列使用utfmb4

CREATE TABLE `person` (
  `name` varchar(255) CHARACTER SET utf8mb4
)

<强>更新

使用下表定义:

CREATE TABLE `person` (
  `name` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

以及以下PHP脚本:

<?php
$mysqli = new mysqli('localhost', 'username', 'password', 'database');
$mysqli->set_charset('utf8mb4');

$mysqli->query("INSERT INTO `person` VALUES ('Altaïr Ibn-La\'Ahad')");

$result = $mysqli->query("SELECT * FROM `person` LIMIT 1");

$person = $result->fetch_object();

if($person)
    printf ("New Person has name %s.\n", $person->name);

$result->close();
$mysqli->close();

当我将“AltaïrIbn-La'Ahad”插入数据库时​​,名称将按原样存储而不做任何更改。该脚本还会打印名称而不做任何更改:“新人的名字是AltaïrIbn-La'Ahad。

我希望这可以帮助您解决问题。如果有的话,请告诉我。

答案 1 :(得分:1)

  

utf8mb4Altaïr是41 6C 74 61 C383C2AF 72

哎哟。那就是“双重编码”。 latin1 EF已转换为utf8 / utf8mb4 C3AF;然后将C3错误地视为latin1 转换为C383,将AF转换为C2AF

以下是可能发生的事情:

  • 客户端的字符编码为utf8(好);和
  • SET NAMES latin1声称客户端有latin1编码;和
  • 表中的列声明为CHARACTER SET utf8(或utf8mb4)(好)。

第二步已由

修复
$mysqli->set_charset('utf8mb4');

我假设你没有混合mysql_*mysqli_*接口。只使用后者。

如何发布简短,可重现的测试用例。

答案 2 :(得分:0)

神秘解决了!使用mysql的安装/升级/配置错误,并且未正确安装utf8mb4。

该函数的问题在于它使用utf8_encode()重新编码db值,并且它以某种方式导致了这些字符<excludes> <exclude>a/**</exclude> <exclude>b/**</exclude> <exclude>c/**</exclude> </excludes> - &gt; v3.0.0