发现问题
问题似乎是$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和collation设置为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)
答案 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
。
以下是可能发生的事情:
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
。