2016-04-27 165 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_但是您還必須修復代碼,以避免繼續存儲這樣。 –

相關問題