Saya sedang menyiapkan server baru dan ingin mendukung UTF-8 sepenuhnya dalam aplikasi web saya. Saya telah mencoba ini di masa lalu pada server yang ada dan sepertinya selalu harus kembali ke ISO-8859-1.
Di mana tepatnya saya perlu mengatur pengkodean / rangkaian karakter? Saya sadar bahwa saya perlu mengkonfigurasi Apache, MySQL, dan PHP untuk melakukan ini - apakah ada beberapa daftar periksa standar yang dapat saya ikuti, atau mungkin memecahkan masalah di mana ketidakcocokan terjadi?
Ini untuk server Linux baru, yang menjalankan MySQL 5, PHP, 5 dan Apache 2.
utf-8
untuk masing-masing secara terpisah - MySQL 5, PHP 5 ATAU Apache 2.Jawaban:
Penyimpanan Data :
Tentukan
utf8mb4
karakter yang ditetapkan pada semua tabel dan kolom teks dalam database Anda. Ini membuat MySQL secara fisik menyimpan dan mengambil nilai yang disandikan secara asli di UTF-8. Perhatikan bahwa MySQL secara implisit akan menggunakanutf8mb4
penyandian jika suatuutf8mb4_*
collation ditentukan (tanpa set karakter eksplisit).Dalam versi MySQL yang lebih lama (<5.5.3), Anda sayangnya terpaksa menggunakan secara sederhana
utf8
, yang hanya mendukung subset karakter Unicode. Saya berharap saya bercanda.Akses Data :
Dalam kode aplikasi Anda (mis. PHP), dalam metode akses DB apa pun yang Anda gunakan, Anda harus mengatur charset koneksi
utf8mb4
. Dengan cara ini, MySQL tidak melakukan konversi dari UTF-8 asalnya ketika menyerahkan data ke aplikasi Anda dan sebaliknya.Beberapa driver menyediakan mekanisme mereka sendiri untuk mengonfigurasi set karakter koneksi, yang keduanya memperbarui keadaan internal sendiri dan menginformasikan MySQL tentang pengkodean yang akan digunakan pada koneksi - ini biasanya pendekatan yang lebih disukai. Dalam PHP:
Jika Anda menggunakan lapisan abstraksi PDO dengan PHP ≥ 5.3.6, Anda dapat menentukan
charset
di DSN :Jika Anda menggunakan mysqli , Anda dapat menghubungi
set_charset()
:Jika Anda terjebak dengan mysql biasa tetapi kebetulan menjalankan PHP ≥ 5.2.3, Anda dapat menelepon
mysql_set_charset
.Jika pengemudi tidak menyediakan mekanisme sendiri untuk menetapkan karakter koneksi set, Anda mungkin harus mengeluarkan permintaan untuk memberitahu MySQL bagaimana aplikasi Anda mengharapkan data pada koneksi yang akan dikodekan:
SET NAMES 'utf8mb4'
.Pertimbangan yang sama tentang
utf8mb4
/utf8
berlaku seperti di atas.Keluaran :
Jika aplikasi Anda mentransmisikan teks ke sistem lain, mereka juga perlu diberi tahu tentang pengkodean karakter. Dengan aplikasi web, browser harus diberi tahu tentang penyandian data yang dikirim (melalui header respons HTTP atau metadata HTML ).
Di PHP, Anda dapat menggunakan
default_charset
opsi php.ini, atau menerbitkanContent-Type
sendiri header MIME secara manual , yang hanya lebih berfungsi tetapi memiliki efek yang sama.Saat menyandikan output menggunakan
json_encode()
, tambahkanJSON_UNESCAPED_UNICODE
sebagai parameter kedua.Masukan :
Sayangnya, Anda harus memverifikasi setiap string yang diterima sebagai UTF-8 yang valid sebelum Anda mencoba menyimpannya atau menggunakannya di mana saja. PHP
mb_check_encoding()
memang berhasil, tetapi Anda harus menggunakannya secara religius. Sebenarnya tidak ada jalan keluar, karena klien jahat dapat mengirimkan data dalam penyandian apa pun yang mereka inginkan, dan saya belum menemukan trik untuk membuat PHP melakukan ini untuk Anda secara andal.Dari bacaan saya tentang spesifikasi HTML saat ini , sub-peluru berikut tidak diperlukan atau bahkan berlaku lagi untuk HTML modern. Pemahaman saya adalah bahwa browser akan bekerja dengan dan mengirimkan data dalam set karakter yang ditentukan untuk dokumen. Namun, jika Anda menargetkan versi HTML yang lebih lama (XHTML, HTML4, dll.), Poin-poin ini mungkin masih berguna:
accept-charset
atribut untuk semua Anda<form>
tag:<form ... accept-charset="UTF-8">
.<form>
menandai.Pertimbangan Kode Lainnya :
Cukup jelas, semua file yang akan Anda layani (PHP, HTML, JavaScript, dll.) Harus dikodekan dalam UTF-8 yang valid.
Anda perlu memastikan bahwa setiap kali Anda memproses string UTF-8, Anda melakukannya dengan aman. Sayangnya, ini adalah bagian yang sulit. Anda mungkin ingin memanfaatkan ekstensi PHP secara
mbstring
ekstensif.Operasi string bawaan PHP tidak secara default aman UTF-8. Ada beberapa hal yang dapat Anda lakukan dengan aman dengan operasi string PHP normal (seperti penggabungan), tetapi untuk sebagian besar hal Anda harus menggunakan
mbstring
fungsi yang setara .Untuk mengetahui apa yang Anda lakukan (baca: bukan mengacaukannya), Anda benar-benar perlu tahu UTF-8 dan cara kerjanya pada level serendah mungkin. Lihatlah salah satu tautan dari utf8.com untuk mendapatkan sumber yang bagus untuk mempelajari semua yang perlu Anda ketahui.
sumber
Saya ingin menambahkan satu hal ke jawaban chazomaticus yang luar biasa :
Jangan lupa tag META (seperti ini, atau versi HTML4 atau XHTML ):
Tampaknya sepele, tetapi IE7 telah memberi saya masalah dengan itu sebelumnya.
Saya melakukan segalanya dengan benar; basis data, koneksi basis data, dan header HTTP Content-Type semuanya diatur ke UTF-8, dan itu berfungsi dengan baik di semua browser lain, tetapi Internet Explorer masih bersikeras menggunakan pengkodean "Eropa Eropa".
Ternyata halaman tersebut tidak memiliki tag META. Menambahkan itu memecahkan masalah.
Edit:
W3C sebenarnya memiliki bagian yang agak besar yang didedikasikan untuk I18N . Mereka memiliki sejumlah artikel yang berkaitan dengan masalah ini - menggambarkan sisi HTTP, (X) HTML dan CSS:
Mereka merekomendasikan penggunaan header HTTP dan meta tag HTML (atau deklarasi XML jika XHTML berfungsi sebagai XML).
sumber
Selain pengaturan
default_charset
di php.ini, Anda dapat mengirim charset yang benar menggunakanheader()
dari dalam kode Anda, sebelum output apa pun:Bekerja dengan Unicode dalam PHP itu mudah selama Anda menyadari bahwa sebagian besar fungsi string tidak bekerja dengan Unicode, dan beberapa mungkin membuat string sepenuhnya . PHP menganggap "karakter" panjangnya 1 byte. Terkadang ini baik-baik saja (misalnya,
explode()
hanya mencari urutan byte dan menggunakannya sebagai pemisah - jadi tidak masalah karakter aktual apa yang Anda cari). Tetapi di lain waktu, ketika fungsi sebenarnya dirancang untuk bekerja pada karakter , PHP tidak tahu bahwa teks Anda memiliki karakter multi-byte yang ditemukan dengan Unicode.Pustaka yang bagus untuk diperiksa adalah phputf8 . Ini menulis ulang semua fungsi "buruk" sehingga Anda dapat bekerja dengan aman pada string UTF8. Ada ekstensi seperti ekstensi mbstring yang mencoba melakukan ini untuk Anda juga, tapi saya lebih suka menggunakan perpustakaan karena lebih portabel (tapi saya menulis produk pasar massal, jadi itu penting bagi saya). Tetapi phputf8 dapat menggunakan mbstring di belakang layar, untuk meningkatkan kinerja.
sumber
Saya menemukan masalah dengan seseorang yang menggunakan PDO dan jawabannya adalah menggunakan ini untuk string koneksi PDO:
Situs tempat saya mengambil ini sedang down, tapi saya bisa mendapatkannya dengan menggunakan cache Google, untungnya.
sumber
$dbh->exec("set names utf8");
; saya lebih suka metode yang disajikan di sini). Btw. ada juga catatan serupa tentang ini sebagai komentar dalam manual PHP: php.net/manual/en/pdo.construct.php#96325 .Dalam kasus saya, saya menggunakan
mb_split
, yang menggunakan regex. Karena itu saya juga harus secara manual memastikan encoding regex adalah utf-8 dengan melakukanmb_regex_encoding('UTF-8');
Sebagai catatan, saya juga menemukan dengan menjalankan
mb_internal_encoding()
bahwa pengkodean internal tidak utf-8, dan saya mengubahnya dengan menjalankanmb_internal_encoding("UTF-8");
.sumber
Pertama-tama jika Anda berada di <5.3PHP maka tidak. Anda punya banyak masalah untuk diatasi.
Saya terkejut bahwa tidak ada yang menyebutkan perpustakaan intl , yang memiliki dukungan yang baik untuk unicode , grapheme , operasi string , lokalisasi dan banyak lagi, lihat di bawah.
Saya akan mengutip beberapa informasi tentang dukungan unicode dalam PHP oleh slide Elizabeth Smith di PHPBenelux'14
INTL
Baik:
Buruk:
mb_string
ICONV
stream_filter_append($fp, 'convert.iconv.ISO-2022-JP/EUC-JP')
DATABAS
Beberapa Gotcha lainnya
Saya akan memperbarui jawaban ini jika ada perubahan fitur ditambahkan dan sebagainya.
sumber
--with-mysqli=mysqlnd --with-pdo-mysql=mysqlnd
opsi.Satu-satunya hal yang saya tambahkan pada jawaban yang luar biasa ini adalah untuk menekankan pada menyimpan file Anda dalam pengkodean utf8, saya telah memperhatikan bahwa browser menerima properti ini lebih dari pengaturan utf8 sebagai pengkodean kode Anda. Setiap editor teks yang layak akan menunjukkan ini kepada Anda, misalnya Notepad ++ memiliki opsi menu untuk pengkondisian file, ini menunjukkan kepada Anda pengkodean saat ini dan memungkinkan Anda untuk mengubahnya. Untuk semua file php saya, saya menggunakan utf8 tanpa BOM.
Beberapa waktu yang lalu saya meminta seseorang untuk menambahkan dukungan utf8 untuk aplikasi php / mysql yang dirancang oleh orang lain, saya perhatikan bahwa semua file dikodekan dalam ANSI, jadi saya harus menggunakan ICONV untuk mengonversi semua file, mengubah tabel database untuk menggunakan utf8 charset dan utf8_general_ci collate, tambahkan 'SET NAMES utf8' ke lapisan abstraksi basis data setelah koneksi (jika menggunakan 5.3.6 atau sebelumnya, Anda harus menggunakan charset = utf8 dalam string koneksi) dan mengubah fungsi string untuk menggunakan multibyte php fungsi string setara.
sumber
Saya baru-baru ini menemukan bahwa menggunakan
strtolower()
dapat menyebabkan masalah di mana data terpotong setelah karakter khusus.Solusinya adalah menggunakan
sumber
Saya baru saja mengalami masalah yang sama dan menemukan solusi yang baik di manual PHP.
Saya mengubah semua penyandian file saya ke UTF8 kemudian penyandian default pada koneksi saya. Ini menyelesaikan semua masalah.
Lihat sumber
sumber
set_charset('utf8mb4')
tidak berfungsi tetapi>set_charset("utf8")
berhasil dan itu tidak benar-benar ditampilkan dalam jawaban lain.set_charset("utf8")
mungkin berfungsi tetapi akan berperilaku berbeda (lihat komentar tentang perbedaan antarautf8
danutf8mb4
dan riwayat versi mysql). Gunakanutf8
jika Anda harus DAN HANYA jika Anda tahu apa yang Anda lakukan !Di PHP, Anda harus menggunakan fungsi multibyte , atau mengaktifkan mbstring.func_overload . Dengan begitu hal-hal seperti strlen akan berfungsi jika Anda memiliki karakter yang membutuhkan lebih dari satu byte.
Anda juga perlu mengidentifikasi rangkaian karakter dari respons Anda. Anda bisa menggunakan AddDefaultCharset, seperti di atas, atau menulis kode PHP yang mengembalikan header. (Atau Anda dapat menambahkan tag META ke dokumen HTML Anda.)
sumber
Dukungan Unicode di PHP masih sangat berantakan. Meskipun mampu mengubah string ISO8859 (yang digunakan secara internal) menjadi utf8, ia tidak memiliki kemampuan untuk bekerja dengan string unicode secara asli, yang berarti semua fungsi pemrosesan string akan memotong-motong dan merusak string Anda. Jadi, Anda harus menggunakan pustaka terpisah untuk dukungan utf8 yang tepat, atau menulis ulang sendiri semua fungsi penanganan string.
Bagian yang mudah hanya menentukan charset di header HTTP dan dalam database dan semacamnya, tetapi tidak ada yang penting jika kode PHP Anda tidak menampilkan UTF8 yang valid. Itu bagian yang sulit, dan PHP memberi Anda hampir tidak ada bantuan di sana. (Saya pikir PHP6 seharusnya memperbaiki yang terburuk dari ini, tapi itu masih beberapa saat lagi)
sumber
Jika Anda ingin server MySQL memutuskan set karakter, dan bukan PHP sebagai klien (perilaku lama; lebih disukai, menurut saya), coba tambahkan
skip-character-set-client-handshake
kemy.cnf
, di bawah[mysqld]
, dan mulai ulangmysql
.Ini dapat menyebabkan masalah jika Anda menggunakan selain UTF8.
sumber
Jawaban teratas sangat bagus. Inilah yang harus saya lakukan pada setup debian / php / mysql reguler:
itu saja !
sumber
jika Anda menginginkan solusi mysql, saya memiliki masalah serupa dengan 2 proyek saya, setelah migrasi server. Setelah mencari dan mencoba banyak solusi saya menemukan ini / tidak ada sebelum ini bekerja):
Setelah menambahkan baris ini ke file konfigurasi saya semuanya berfungsi dengan baik!
Saya menemukan solusi ini https://www.w3schools.com/PHP/func_mysqli_set_charset.asp ketika saya sedang mencari untuk menyelesaikan penyisipan dari permintaan html
semoga berhasil!
sumber
Hanya sebuah catatan:
Anda menghadapi masalah karakter non-latin Anda menunjukkan sebagai
?????????
, Anda mengajukan pertanyaan, dan itu bisa ditutup dengan referensi untuk pertanyaan kanonik ini, Anda mencoba segalanya dan tidak peduli apa yang Anda lakukan Anda masih mendapatkan??????????
dariMySQL
.Itu sebagian besar karena Anda menguji data lama Anda yang telah dimasukkan ke database menggunakan charset yang salah dan dikonversi dan disimpan untuk benar-benar karakter tanda tanya
?
. Yang berarti Anda kehilangan teks asli Anda selamanya dan apa pun yang Anda coba akan Anda dapatkan???????
.sedang menerapkan apa yang telah Anda pelajari dari jawaban pertanyaan ini pada data baru dapat menyelesaikan masalah Anda.
sumber
Saya punya masalah ini saat menampilkan tabel. Saya hanya menempatkan ini pada setiap variabel output gema:
sumber