2016-04-27 277 views
1

问题发现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` 
+0

没有转换?你的意思是BLOB?处理UTF8的经验法则是:总是记录转换+编码+解码方法。 – mootmoot

+0

什么是BLOB?我认为php为我处理...如果PHP使用utf8并从MySQL中获取utf8mb4,需要什么样的转换? –

+0

BLOB是一种MySQL数据类型,通常用于存储大量的文本或二进制数据。看到这里http://dev.mysql.com/doc/refman/5.7/en/blob.html。 – Vadim

回答

0

Mistery解决了!有一个不好的安装/升级/配置与MySQL和utf8mb4未正确安装。

该函数的问题在于它使用utf8_encode()重新编码db值,并以某种方式导致这些类型的字符óó

+1

请你详细告诉我们你是如何解决这个问题的。我有同样的问题,并在此刻拔出我的头发:( –

+0

对不起,我正在享受我的假期:) MySQL(在我的情况下MariaDB)缺乏neccesary文件,所以编码不存在。这些文件需要编译(我认为重新编译必要的标志)或重新安装最新版本。这发生在一个旧的cent os 5服务器上,所以在最近的版本中这不应该发生,事实上我安装cent os 6.7和utf8mb4被发现没有问题。 –

1

问题可能来自一个事实,即你是干在你的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伊本拉阿阿德。

我希望这可以帮助你解决你的问题。让我知道,如果它确实或没有。

+0

我使用utf8mb4作为charset和utf8mb4_unicode_ci作为所有表格/列的归类。 –

+0

插入数据时,它在数据库中看起来是否正确:1)直接插入数据库时​​; 2)用PHP插入时? – Vadim

+0

当我直接插入数据时,它看起来是这样。但是,当我插入它与PHP它取决于我如何对待用户输入在PHP中。如果我使用过滤器,它会转换特殊字符,但它们会显示为它们应该显示的字符。例如:我插入名称“AltaïrIbn-La'Ahad”,这是存储的“AltaïrIbn-La ' Ahad”。如果我不过滤它只是ï什么转换为Ã。 –

1

utf8mb4阿泰尔是41 6C 74 61 72 C383C2AF

哎哟。这是“双重编码”。 latin1 EF已转换为utf8/utf8mb4 C3AF;然后将C3,错误地视为拉丁语1被转换为C383AFC2AF

下面是可能发生的事情:

  • 客户端已经字符编码成UTF-8(好);和
  • SET NAMES latin1谎称声称客户端有latin1编码;和
  • 表中的列声明CHARACTER SET utf8(或utf8mb4)(好)。

这第二步应该已得到修复

$mysqli->set_charset('utf8mb4'); 

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

如何发布一个简短的,可重复的测试用例。

+0

是的我很想能够重现它,但它可能是在我的框架/应用程序本身的一些问题,我不知道从哪里开始......但是,我有这个类的功能是选择并显示一切ok的时候mysqli charset是utf8mb4,但我的应用程序的其余部分显示了 。当mysqli字符集只是utf8这个函数不会显示 ,但典型的html编码问题,我要更新我的问题,以添加此。 –

+0

显示很棘手。浏览器是'宽容'的;他们会尝试不同的方式来解释字节,并在某些情况下,使乱码文本看起来正确。当黑钻不能成功时就会发生黑钻。 –

+0

如果您已经存储了大量数据“双重编码”,这里是关于修复数据的信息:http://mysql.rjweb.org/doc.php/charcoll#fixing_double_encoding_但是您还必须修复代码,以避免继续存储这样。 –

相关问题