mysqli的不设置字符集到utf8mb4
这个问题似乎是$mysqli->set_charset()
不接受`utf8mb4' 作为一个有效的编码(在第一更新正如我‘猜测’)。 MySQL版本是5.5.41,PHP版本是5.4.41(没有问题)。
很抱歉的标题,我一直在寻找/读什么/问题在那里可以和我已经太糊涂了这个...
我使用utf8mb4最近开始在MySQL 。我使用utf8mb4作为字符集和utf8mb4_unicode_ci作为所有表/列的归类。
所以我第一次我改变:
$mysqli->set_charset('utf8');
到
$mysqli->set_charset('utf8mb4');
确信我的PHP文件是UTF8(我使用Visual Studio代码以便文件在UTF-8中创建默认情况下),和PHP/HTML头被设置为UTF-8:
的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不能正常工作,当你改变一些数据库/表配置和唯一的方法是旧的方式(运行自己的查询),但我didn我还没试过,但是。我运行查询来设置所有表/列的字符集和排序规则。
您认为如何?
UPDATE
我开始认为的mysqli不接受utf8mb4为有效的字符编码,并从PHP使用UTF-8,而不是来自MySQL的...我也觉得mysql的fckd了创建utf8mb4代替更新现有的utf8以支持4个字节....
因为我使用mysqli字符集utf8进行测试,所有东西都按原样存储并显示(mysql字符集和排序规则设置为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?为什么当utf8mb4设置为mysqli时,php显示特殊字符ï
为�
?
有人可以确认mysqli::set_charset
接受utf8mb4作为一个有效的编码吗?
UPDATE 3
我有一个类函数,其选择从表中的字符串“ES”,例如:Iniciar Sesión
(这是什么存储),并且如果mysqli的字符集是UTF8,正被选择什么/显示为Iniciar Sesión
。
这可能是一个完全不同的问题,但它显然是另一个编码问题。根据我的理解,如果表/列是utf8mb4并且mysqli设置为utf8,则mysql必须从utf8(3字节)到ut8mb4(全字节支持)进行编码。所以这意味着mysqli
不使用来自php的utf8,而是使用mysql。这是正确的,对吗?
我的应用程序,目前有一个粗略的时间与编码...(但也许是一些服务器的配置问题...)
UPDATE 4
问题就在这里?我真的没有关于这种配置的思路:
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)
UPDATE 4-1/2(从评论复制)
CREATE TABLE es` (
id int(11) NOT NULL AUTO_INCREMENT,
name varchar(30) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
text varchar(100) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
PRIMARY KEY (id),
UNIQUE KEY name (name)
) ENGINE=InnoDB AUTO_INCREMENT=76 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci`
Mistery解决了!有一个不好的安装/升级/配置与MySQL和utf8mb4未正确安装。
该函数的问题在于它使用utf8_encode()重新编码db值,并以某种方式导致这些类型的字符ó
→ó
。
请你详细告诉我们你是如何解决这个问题的。我有同样的问题,并在此刻拔出我的头发:( –
对不起,我正在享受我的假期:) MySQL(在我的情况下MariaDB)缺乏neccesary文件,所以编码不存在。这些文件需要编译(我认为重新编译必要的标志)或重新安装最新版本。这发生在一个旧的cent os 5服务器上,所以在最近的版本中这不应该发生,事实上我安装cent os 6.7和utf8mb4被发现没有问题。 –
问题可能来自一个事实,即你是干在你的MySQL列定义中不使用utf8mb4
(至少你没有说你使用的是什么编码)。
这里是与使用utfmb4
列一个MySQL表定义的一个示例:
CREATE TABLE `person` (
`name` varchar(255) CHARACTER SET utf8mb4
)
UPDATE
使用下表定义:
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ïr伊本拉阿阿德。”
我希望这可以帮助你解决你的问题。让我知道,如果它确实或没有。
我使用utf8mb4作为charset和utf8mb4_unicode_ci作为所有表格/列的归类。 –
插入数据时,它在数据库中看起来是否正确:1)直接插入数据库时; 2)用PHP插入时? – Vadim
当我直接插入数据时,它看起来是这样。但是,当我插入它与PHP它取决于我如何对待用户输入在PHP中。如果我使用过滤器,它会转换特殊字符,但它们会显示为它们应该显示的字符。例如:我插入名称“AltaïrIbn-La'Ahad”,这是存储的“AltaïrIbn-La ' Ahad”。如果我不过滤它只是ï什么转换为Ã。 –
utf8mb4阿泰尔是41 6C 74 61 72 C383C2AF
哎哟。这是“双重编码”。 latin1 EF
已转换为utf8/utf8mb4 C3AF
;然后将C3
,错误地视为拉丁语1被转换为C383
和AF
至C2AF
。
下面是可能发生的事情:
- 客户端已经字符编码成UTF-8(好);和
-
SET NAMES latin1
谎称声称客户端有latin1编码;和 - 表中的列声明
CHARACTER SET utf8
(或utf8mb4)(好)。
这第二步应该已得到修复
$mysqli->set_charset('utf8mb4');
我假设你是不是混合mysql_*
和mysqli_*
接口。只使用后者。
如何发布一个简短的,可重复的测试用例。
是的我很想能够重现它,但它可能是在我的框架/应用程序本身的一些问题,我不知道从哪里开始......但是,我有这个类的功能是选择并显示一切ok的时候mysqli charset是utf8mb4,但我的应用程序的其余部分显示了 。当mysqli字符集只是utf8这个函数不会显示 ,但典型的html编码问题,我要更新我的问题,以添加此。 –
显示很棘手。浏览器是'宽容'的;他们会尝试不同的方式来解释字节,并在某些情况下,使乱码文本看起来正确。当黑钻不能成功时就会发生黑钻。 –
如果您已经存储了大量数据“双重编码”,这里是关于修复数据的信息:http://mysql.rjweb.org/doc.php/charcoll#fixing_double_encoding_但是您还必须修复代码,以避免继续存储这样。 –
没有转换?你的意思是BLOB?处理UTF8的经验法则是:总是记录转换+编码+解码方法。 – mootmoot
什么是BLOB?我认为php为我处理...如果PHP使用utf8并从MySQL中获取utf8mb4,需要什么样的转换? –
BLOB是一种MySQL数据类型,通常用于存储大量的文本或二进制数据。看到这里http://dev.mysql.com/doc/refman/5.7/en/blob.html。 – Vadim