Mysql
 sql >> Base de Dados >  >> RDS >> Mysql

uma maneira permanente de fazer mysqli->set_charset()?


Você diagnosticou o problema básico corretamente:Embora você possa alterar o charset do cliente MySQL padrão no my.cnf da máquina cliente ou .my.cnf , esses arquivos não são usados ​​pelo PHP.

Se você pensar em como as extensões MySQLi/MySQL do PHP funcionam, isso fará sentido -- elas não têm nada a ver com o mysql programa cliente e não vão rastrear seu sistema de arquivos para arquivos de configuração, porque eles usam libmysql diretamente.

Para alterar o charset padrão real do libmysql, você só precisa reconstruir o libmysql. Essa pode não ser uma resposta que você goste (já que você está usando binários pré-compilados do MySQL), mas é a resposta real. Os padrões são definidos em tempo de compilação e podem ser substituídos em tempo de execução.

Se você não quiser fazer isso e chamar set_charset() te incomoda, minha sugestão seria simplesmente estender a classe MySQLi e usar essa classe no lugar de mysqli. ou seja:
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");
  } 
} 

Normalmente em um aplicativo você terá algum tipo de camada de abstração de banco de dados de qualquer maneira, então você pode ter essa camada usando MyDB em vez de mysqli, ou você pode ter essa camada ser MyDB e adicione ou substitua quaisquer métodos que você quiser (eu fiz isso com aplicativos simples sem ORM).

É uma boa prática sempre ter algum tipo de camada de abstração de banco de dados, mesmo que comece como apenas class MyDB extends mysqli {} porque então você nunca terá que pesquisar/substituir toda a sua base de código para fazer pequenas alterações.

RE:sua solução alternativa, como você explica, isso essencialmente codifica todo o seu servidor db para UTF-8, independentemente do que os clientes solicitam. Em vez de ter vários bancos de dados, cada um com seu próprio charset, o servidor só funciona com UTF-8 e pode desvirtuar os dados silenciosamente se os clientes se conectarem com outro charset. Isso está fundamentalmente errado porque você efetivamente moveu um aspecto da configuração do seu aplicativo (conjunto de caracteres do banco de dados) da máquina do aplicativo/cliente para o servidor de banco de dados onde ele realmente não pertence.

Se você pensar nas camadas da pilha de aplicativos,
[server] <=> [network] <=> [client libmysql] <=> [PHP binary] <=> [app]

então você entenderá que o local "correto" para uma configuração específica de aplicativo como essa é no próprio aplicativo, não em outro lugar na pilha. Você pode não gostar de ter que especificar o conjunto de caracteres do seu banco de dados em PHP, mas se você pensar sobre isso, é realmente onde ele pertence, porque também é onde você está especificando o próprio banco de dados ao qual deseja se conectar -- é um parâmetro de conexão, não é um problema de configuração do servidor. Codificar o conjunto de caracteres em qualquer outro lugar torna seu aplicativo não portátil.