Du har diagnosticeret det grundlæggende problem korrekt:Mens du kan ændre standard MySQL-klient-tegnsættet i klientmaskinens my.cnf
eller .my.cnf
, disse filer bruges ikke af PHP.
Hvis du tænker på, hvordan PHPs MySQLi/MySQL-udvidelser fungerer, vil dette give mening -- de har intet at gøre med mysql
klientprogram og vil ikke crawle dit filsystem for konfigurationsfiler, fordi de bruger libmysql
direkte.
For at ændre libmysqls faktiske standardtegnsæt, skal du blot genopbygge libmysql. Det er måske ikke et svar, du kan lide (da du bruger prækompilerede MySQL-binære filer), men det er det faktiske svar. Standardindstillingerne er indstillet på kompileringstidspunktet og kan derefter tilsidesættes under kørsel.
Hvis du ikke ønsker at gøre dette og kalder set_charset() irriterer dig, ville mit forslag være at udvide MySQLi-klassen og bruge den klasse i stedet for mysqli. dvs.:
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");
}
}
Typisk har du i en applikation alligevel en form for databaseabstraktionslag, så du kan enten få dette lag til at bruge MyDB i stedet for mysqli, eller du kan få dette lag til at være MyDB og tilføj eller tilsidesæt de metoder, du ønsker (jeg har gjort dette med simple ORM-løse apps).
Det er en god praksis altid at have en form for databaseabstraktionslag, selvom det starter som bare class MyDB extends mysqli {}
for så behøver du aldrig søge/erstatte hele din kodebase for at lave små ændringer.
RE:din løsning, som du forklarer, hardkoder dette i det væsentlige hele din db-server til UTF-8, uanset hvad klienter anmoder om. I stedet for at have flere databaser, hver med sit eget tegnsæt, fungerer serveren kun med UTF-8 og kan i det stille mangle data, hvis klienter forbinder med et andet tegnsæt. Dette er grundlæggende forkert, fordi du effektivt har flyttet et aspekt af din applikations konfiguration (databasetegnsæt) fra app-/klientmaskinen til databaseserveren, hvor det ikke rigtig hører hjemme.
Hvis du tænker på applikationsstakkens lag,
[server] <=> [network] <=> [client libmysql] <=> [PHP binary] <=> [app]
så vil du forstå, at det "korrekte" sted for en app-specifik konfiguration som denne er i selve appen, ikke andre steder i stakken. Du kan måske ikke lide at skulle angive din databases tegnsæt i PHP, men hvis du tænker over det, er det virkelig der, det hører hjemme, fordi det også er der, du angiver selve databasen, som du vil oprette forbindelse til -- det er en forbindelsesparameter, ikke et serverkonfigurationsproblem. Hardkodning af tegnsættet andre steder gør din applikation ikke-bærbar.