2012-10-23 19 views
6

Jest to prawdopodobnie coś prostego. Przysięgam, że szukałem odpowiedzi w Internecie i jej nie znalazłem. Ponieważ mój szczególny przypadek jest trochę nietypowy, postanowiłem w końcu tutaj zapytać.Manipulowanie danymi utf8mb4 z MySQL z PHP

Mam kilka tabel w MySQL, których używam dla programu języka chińskiego. Musi być w stanie obsłużyć każdą możliwą chińską postać, w tym rzadkie, które nie obsługują wielkich czcionek. Komórka próbki w tabeli może być w ten sposób:

東 菄 鶇 䍶 倲 涷 蝀 凍 鯟 崠 埬 䰤

w celu uzyskania że prawo do pracy w bazie danych, miałem aby ustawić kodowanie/sortowanie na utf8mb4. Jak na razie dobrze. Niestety kiedy ciągnąć ten sam ciąg znaków w PHP, to zostanie wydrukowana jako to:?

東 菄 鶇 䍶 倲 ?? 涷 蝀 凍 鯟 崠 埬 䰤

Jak mogę wreszcie zabić od pozostałych znaków zapytania i sprawić, by były wyświetlane jako glify unicode, które powinny być? Mam samą stronę php, używając kodowania UTF8 w tagu i jako metatag.

Dlaczego nie mogą się ze sobą komunikować? Co ja robię źle?

+0

Czy ustawiasz kodowanie połączenia z bazą danych? Jeśli tak, to w jaki sposób i do czego? Czy znaki są faktycznie konwertowane gdzieś lub czy jest to tylko problem z wyświetlaniem? Co 'bin2hex()' w tym ciągu daje ci w PHP? – deceze

Odpowiedz

15

Po prostu domyślam się, że ustawiasz tabelę na utf8mb4, ale kodowanie połączenia jest ustawione na utf8. Musisz również ustawić go na utf8mb4, w przeciwnym razie MySQL będzie konwertować przechowywane dane utf8mb4 na utf8, z których ta ostatnia nie może kodować "wysokich" znaków Unicode. (Tak, to jest specyfiką MySQL).

Na surowego połączenia MySQL, będzie ona musiała wyglądać następująco:

SET NAMES 'utf8mb4'; 
SELECT * FROM `my_table`; 

Będziesz musiał dostosować się, że do najlepszej drodze do klienta, w zależności od o tym, jak połączyć się z MySQL z PHP (mysql, mysqli lub PDO).


Aby naprawdę wyjaśnić (tak, używając rozszerzenia mysql_ dla uproszczenia, nie rób tego w domu):

mysql_connect(...); 
mysql_select_db(...); 
mysql_set_charset('utf8mb4');  // adapt to your mysql connector of choice 

$r = mysql_query('SELECT * FROM `my_table`'); 

var_dump(mysql_fetch_assoc($r)); // data will be UTF8 encoded 
+0

Uzyskuję dostęp z PHP i aktualnie używam 'mb_internal_encoding ('UTF-8');' Czy to wpływa na rozwiązanie? Czy istnieje coś takiego jak 'mb_internal_encoding ('UTF-8MB4');'? – Yhilan

+0

Nie, 'mb_internal_encoding' ustawia tylko wewnętrzne kodowanie dla funkcji' mb_', nie ma nic wspólnego z MySQL. Otrzymasz normalne UTF-8 z powrotem z MySQL, 'utf8mb4' jest tylko wewnętrzną rzeczą dla MySQL. – deceze

+0

Więc w jaki sposób użyć SET NAMES z poziomu PHP? Czy mam zamiar o tym źle i powinien w jakiś sposób ustawić go z wewnątrz coś jak phpmyadmin? – Yhilan

2

Wystarczy dodać do użytkownika @ deceze odpowiedź, polecam dobrze skonfigurowany Serwer MySQL (dla mnie, w /etc/mysql/mysql.conf.d/mysqld.cnf). Oto opcje konfiguracyjne, aby upewnić się, że używasz utfmb4, chociaż zalecam przechodzenie przez każdą opcję konfiguracji MySQL, choć zniechęcając, jest wiele domyślnych ustawień, które są bardzo nieoptymalne.

[client] 

default-character-set   = utf8mb4 

[mysql] 

default_character_set   = utf8mb4 

[mysqld] 

init-connect     = "SET NAMES utf8mb4" 
character-set-client-handshake = FALSE 
character-set-server   = "utf8mb4" 
collation-server    = "utf8mb4_unicode_ci" 
autocommit      = 1 
block_encryption_mode   = "aes-256-cbc" 

Ten ostatni to taki, który powinien być domyślny. Ponadto, init-connect radzi sobie z tym, że nie trzeba tego wykonywać za każdym razem. Utrzymuje kod w czystości.Teraz uruchom:

SHOW VARIABLES WHERE Variable_name LIKE 'character\_set\_%' OR Variable_name LIKE 'collation%'; 

Należy powrócić coś jak następuje:

+--------------------------+--------------------+ 
| Variable_name   | Value    | 
+--------------------------+--------------------+ 
| character_set_client  | utf8mb4   | 
| character_set_connection | utf8mb4   | 
| character_set_database | utf8mb4   | 
| character_set_filesystem | binary    | 
| character_set_results | utf8mb4   | 
| character_set_server  | utf8mb4   | 
| character_set_system  | utf8    | 
| collation_connection  | utf8mb4_unicode_ci | 
| collation_database  | utf8mb4_unicode_ci | 
| collation_server   | utf8mb4_unicode_ci | 
+--------------------------+--------------------+ 

I wygląda na to, że robisz to już, ale nie zaszkodzi jednoznacznie określić na tworzenie tabeli:

CREATE TABLE `mysql_table` (
    `mysql_column` BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT, 
    PRIMARY KEY (`mysql_column`) 
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; 

Mam nadzieję, że to komuś pomaga.

+0

nie zapomnij zrestartować mysql za pomocą 'service mysqld start' lub' /etc/init.d/mysqld restart' po zmianie pliku konfiguracyjnego – salvob

+1

Dlaczego istnieją ustawienia o tej samej nazwie, ale ze myślnikami lub podkreśleniami i cytatami lub bez cytatów? –

+0

Bo jestem opóźniony? Edytowane (dzięki!) – Eugene

Powiązane problemy