Anda telah mendiagnosis masalah dasar dengan benar:Meskipun Anda dapat mengubah rangkaian karakter klien MySQL default di my.cnf
mesin klien atau .my.cnf
, file-file ini tidak digunakan oleh PHP.
Jika Anda berpikir tentang cara kerja ekstensi MySQLi/MySQL PHP, ini masuk akal -- mereka tidak ada hubungannya dengan mysql
program klien dan tidak akan merayapi sistem file Anda untuk file konfigurasi, karena mereka menggunakan libmysql
secara langsung.
Untuk mengubah charset default libmysql yang sebenarnya, Anda hanya perlu membangun kembali libmysql. Itu mungkin bukan jawaban yang Anda suka (karena Anda menggunakan binari MySQL yang telah dikompilasi sebelumnya), tetapi itu adalah jawaban yang sebenarnya. Defaultnya disetel pada waktu kompilasi, dan kemudian dapat diganti saat runtime.
Jika Anda tidak ingin melakukan ini dan memanggil set_charset() mengganggu Anda, saran saya adalah dengan memperluas kelas MySQLi dan menggunakan kelas itu sebagai ganti mysqli. yaitu:
class MyDB extends mysqli {
// (You could set defaults for the params here if you want
// i.e. $host = 'myserver', $dbname = 'myappsdb' etc.)
public function __construct($host = NULL, $username = NULL, $dbname = NULL, $port = NULL, $socket = NULL) {
parent::__construct($host, $username, $dbname, $port, $socket);
$this->set_charset("utf8");
}
}
Biasanya dalam sebuah aplikasi Anda akan memiliki semacam lapisan abstraksi basis data, jadi Anda dapat membuat lapisan ini menggunakan MyDB alih-alih mysqli, atau Anda dapat membuat lapisan ini menjadi MyDB dan tambahkan atau timpa metode apa pun yang Anda inginkan (saya telah melakukannya dengan aplikasi sederhana tanpa ORM).
Ini adalah praktik yang baik untuk selalu memiliki semacam lapisan abstraksi database, bahkan jika itu dimulai hanya sebagai class MyDB extends mysqli {}
karena dengan begitu Anda tidak perlu lagi mencari/mengganti seluruh basis kode untuk membuat perubahan kecil.
RE:solusi Anda, seperti yang Anda jelaskan, ini pada dasarnya meng-hardcode seluruh server db Anda ke UTF-8 terlepas dari apa yang diminta klien. Alih-alih memiliki banyak database, masing-masing dengan rangkaian karakternya sendiri, server hanya bekerja dengan UTF-8 dan dapat secara diam-diam memotong data jika klien terhubung dengan rangkaian karakter lain. Ini pada dasarnya salah karena Anda telah secara efektif memindahkan satu aspek dari konfigurasi aplikasi Anda (database charset) dari mesin aplikasi/klien ke server database yang sebenarnya bukan miliknya.
Jika Anda berpikir tentang lapisan tumpukan aplikasi,
[server] <=> [network] <=> [client libmysql] <=> [PHP binary] <=> [app]
maka Anda akan memahami bahwa tempat yang "benar" untuk konfigurasi khusus aplikasi seperti ini adalah di aplikasi itu sendiri, bukan di tempat lain di tumpukan. Anda mungkin tidak suka harus menentukan charset database Anda di PHP, tetapi jika Anda memikirkannya, itu benar-benar tempatnya, karena itu juga tempat Anda menentukan database itu sendiri yang ingin Anda sambungkan -- ini adalah parameter koneksi, bukan masalah konfigurasi server. Hardcoding charset di tempat lain membuat aplikasi Anda tidak portabel.