Prawidłowo zdiagnozowałeś podstawowy problem:Chociaż możesz zmienić domyślny zestaw znaków klienta MySQL w my.cnf
komputera klienckiego lub .my.cnf
, te pliki nie są używane przez PHP.
Jeśli pomyślisz o tym, jak działają rozszerzenia PHP MySQLi/MySQL, będzie to miało sens — nie mają one nic wspólnego z mysql
programu klienckiego i nie będą indeksować systemu plików w poszukiwaniu plików konfiguracyjnych, ponieważ używają libmysql
bezpośrednio.
Aby zmienić rzeczywisty domyślny zestaw znaków libmysql, wystarczy przebudować libmysql. To może nie być odpowiedź, którą lubisz (ponieważ używasz prekompilowanych plików binarnych MySQL), ale jest to rzeczywista odpowiedź. Wartości domyślne są ustawiane w czasie kompilacji, a następnie mogą zostać nadpisane w czasie wykonywania.
Jeśli nie chcesz tego robić, a wywołanie set_charset() cię denerwuje, sugeruję po prostu rozszerzyć klasę MySQLi i użyć tej klasy zamiast mysqli. tj.:
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");
}
}
Zazwyczaj w aplikacji i tak będziesz mieć jakąś warstwę abstrakcji bazy danych, więc możesz albo użyć tej warstwy MyDB zamiast mysqli, albo możesz mieć tę warstwę być MyDB i dodaj lub zastąp dowolne metody (zrobiłem to za pomocą prostych aplikacji bez ORM).
Dobrą praktyką jest zawsze mieć jakąś warstwę abstrakcji bazy danych, nawet jeśli zaczyna się jako class MyDB extends mysqli {}
ponieważ wtedy nigdy nie będziesz musiał przeszukiwać/zamieniać całej bazy kodu, aby dokonać drobnych zmian.
RE:twoje obejście, jak wyjaśniasz, to zasadniczo koduje cały serwer bazy danych do UTF-8, niezależnie od tego, czego żądają klienci. Zamiast mieć wiele baz danych, każda z własnym zestawem znaków, serwer działa tylko z UTF-8 i może po cichu zniekształcać dane, jeśli klienci łączą się z innym zestawem znaków. Jest to zasadniczo błędne, ponieważ skutecznie przeniosłeś jeden aspekt konfiguracji aplikacji (zestaw znaków bazy danych) z aplikacji/maszyny klienta na serwer bazy danych, do którego tak naprawdę nie należy.
Jeśli myślisz o warstwach stosu aplikacji,
[server] <=> [network] <=> [client libmysql] <=> [PHP binary] <=> [app]
wtedy zrozumiesz, że „właściwe” miejsce dla konfiguracji specyficznej dla aplikacji, takiej jak ta, znajduje się w samej aplikacji, a nie w innym miejscu stosu. Możesz nie lubić konieczności określania zestawu znaków swojej bazy danych w PHP, ale jeśli się nad tym zastanowisz, to tak naprawdę jest to miejsce, do którego należy, ponieważ jest to również miejsce, w którym określasz samą bazę danych, z którą chcesz się połączyć -- jest to parametr połączenia, nie jest to problem z konfiguracją serwera. Zakodowanie zestawu znaków w dowolnym innym miejscu sprawia, że Twoja aplikacja jest nieprzenośna.