set_charset - set charset php
una forma permanente de hacer mysqli-> set_charset()? (2)
después de configurar todas las opciones de archivo de configuración y tiempo de ejecución para el conjunto de caracteres que puedo encontrar en utf-8, las nuevas conexiones mysqli hechas con php todavía tienen su conjunto de caracteres latin1, lo que efectivamente significa que $mysqli->set_charset(''utf8'')
llamar a $mysqli->set_charset(''utf8'')
cada vez que me conecto.
$mysqli = new mysqli(DB_HOST, DB_USER, DB_PASS, DB_NAME);
if ($mysqli->connect_error)
err_handle("mysql connect error({$mysqli->connect_errno}).");
if (!$mysqli->set_charset("utf8"))
err_handle("db error({$mysqli->errno}).");
Me pregunto si hay una forma permanente de hacer esto.
Problema similar fue encontrado en este post .
una consulta " show variables like ''character_set%''
" en el servidor mysql antes de llamar a $mysqli->set_charset(''utf8'')
muestra:
(esta parte fue ambigua en las revoluciones anteriores)
character_set_client latin1
character_set_connection latin1
character_set_database utf8
character_set_filesystem binary
character_set_results latin1
character_set_server utf8
character_set_system utf8
el juego de caracteres del cliente, la conexión y los resultados solo se puede cambiar a utf8 con $mysqli->set_charset(''utf8'')
en tiempo de ejecución. después de eso se muestra:
character_set_client utf8
character_set_connection utf8
character_set_database utf8
character_set_filesystem binary
character_set_results utf8
character_set_server utf8
character_set_system utf8
yo tengo
default_charset = "utf-8"
establecido en php.ini, y
[client]
default-character-set=utf8
...
[mysqld]
## This option is deprecated in favor of --character-set-server.
#default-character-set=utf8
establecido en my.cnf.
el conjunto de caracteres predeterminado para mis tablas también es utf8.
Parece que las opciones "[cliente]" solo afectan la herramienta cmd "mysql" y no tienen nada que ver con php.
el valor de retorno de $mysqli->character_set_name()
siempre es latin1 no importa lo que haga, hasta que se $mysqli->set_charset(''utf8'')
.
Supongo que "latin1" es una cosa de mysql, ya que no puedo recordar nada más que por defecto sea "latin1" en mi sistema.
^ actualización: de acuerdo con el manual de mysql 9.1.4 , 9.1.5 y 5.1.3 , el cliente debe proporcionar character_set_client
. Supongo que php no lo proporciona en la conexión y mysql usa el conjunto de caracteres latín1 .
Estoy ejecutando php 5.3 en debian wheezy con mysql 5.1.
¿cualquier sugerencia?
Actualizado con información de los comentarios:
Olvidé mencionar la directiva skip-character-set-client-handshake
y por qué me resistí a usarla.
a primera vista, pensé que ignorar el saludo podría resultar en la situación de que el cliente habla latin1 mientras el servidor habla utf8 . ¿Cómo convierte el servidor la cadena de caracteres charset character_set_client
a character_set_server
sin saber el charset actualmente en uso?
corrígeme si me equivoco, por favor. Voy a experimentar con esta configuración más tarde hoy para ver si funciona.
Actualizado con workaroud :
asegúrese de que todo funcione bajo utf-8 (o cualquier conjunto de caracteres preferible). luego agregue la línea skip-character-set-client-handshake
a my.cnf
.
esto funciona para mí hasta ahora. Experimenté con algunos caracteres utf-8 de doble ancho. Tanto la insert
como la select
correctamente y se muestran correctamente en el navegador.
lo que significa saltarse el apretón de manos aún no está claro. y el servidor mysql ahora ya no puede utilizar ningún juego de caracteres, excepto utf-8, lo que hace que esta solución no sea práctica ya que simplemente no puedo aplicar esta configuración a todos los servidores en los que se ejecuta mi sitio web.
así que no estoy adoptando esta solución. Más comentarios y respuestas son muy apreciados.
De acuerdo a las siguientes publicaciones de MySQL.
http://dev.mysql.com/doc/refman/5.0/en/charset-connection.html http://dev.mysql.com/doc/refman/5.0/en/charset-applications.html
su configuración no es completamente correcta, es decir
utilizar
[mysqld]
character-set-server=utf8
collation-server=utf8_general_ci
en lugar de
[mysqld]
default-character-set=utf8
para el cliente que solo encontré
[mysql]
default-character-set=utf8
no
[client]
default-character-set=utf8
Intenta y dame algunos comentarios.
Puedo recordar que una vez leí sobre una configuración var para desactivar la posibilidad de que un cliente cambie la configuración de caracteres. Pero no puedo encontrar el ref en la documentación de mysql ahora. Si lo encuentro te lo hago saber.
Espero que ayude.
Saludos
ACTUALIZAR
@Unisland BTW Encontré este hilo http://www.webmasterworld.com/php/3553642.htm donde se discute un problema similar
Prueba cualquiera
Así que puedes intentar agregar un:
[mysqld]
init-connect = ''SET NAMES utf8''
o
[cliente]
conjunto de caracteres predeterminado = utf8[mysqld]
conjunto de caracteres-servidor = utf8
conjunto de caracteres predeterminado = utf8
default-collation = utf8_unicode_ci
conjunto de caracteres-cliente = utf8
para configurar esto como predeterminado para todas las conexiones, o comience con estas consultas después de que su script específico se conecte a la base de datos antes de enviar otras consultas: SET NAMES utf8; SET CHARACTER_SET utf8;
Ha diagnosticado correctamente el problema básico: si bien puede cambiar el conjunto de caracteres del cliente MySQL predeterminado en la máquina cliente my.cnf
o .my.cnf
, PHP no usa estos archivos.
Si piensa en cómo funcionan las extensiones MySQLi / MySQL de PHP, esto tendrá sentido: no tienen nada que ver con el programa cliente mysql
y no rastrearán su sistema de archivos en busca de archivos de configuración, ya que usan libmysql
directamente.
Para cambiar el conjunto de caracteres predeterminado real de libmysql, solo tendrá que reconstruir libmysql. Puede que esa no sea una respuesta que te guste (ya que estás usando archivos binarios de MySQL precompilados), pero es la respuesta real. Los valores predeterminados se establecen en el momento de la compilación, y luego se pueden anular en el tiempo de ejecución.
Si no quieres hacer esto y llamar a set_charset () te molesta, mi sugerencia sería simplemente extender la clase MySQLi y usar esa clase en lugar de mysqli. es decir:
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");
}
}
Por lo general, en una aplicación, de todos modos, tendrá algún tipo de capa de abstracción de la base de datos, así que puede hacer que esta capa use MyDB en lugar de mysqli, o puede hacer que esta capa sea MyDB y agregar o anular cualquier método que desee (lo he hecho esto con aplicaciones simples sin ORM).
Es una buena práctica tener siempre algún tipo de capa de abstracción de base de datos, incluso si comienza como solo la class MyDB extends mysqli {}
porque nunca tendrá que buscar / reemplazar todo el código base para hacer pequeños cambios.
RE: su solución, como explica, esto esencialmente codifica su servidor de bases de datos completo a UTF-8 independientemente de lo que soliciten los clientes. En lugar de tener varias bases de datos, cada una con su propio conjunto de caracteres, el servidor solo funciona con UTF-8 y puede manipular los datos de forma silenciosa si los clientes se conectan con otro conjunto de caracteres. Esto es fundamentalmente incorrecto porque efectivamente ha movido un aspecto de la configuración de su aplicación (conjunto de datos de la base de datos) desde la máquina de la aplicación / cliente al servidor de la base de datos donde realmente no pertenece.
Si piensas en las capas de la pila de aplicaciones,
[server] <=> [network] <=> [client libmysql] <=> [PHP binary] <=> [app]
entonces comprenderá que el lugar "correcto" para una configuración específica de la aplicación como esta se encuentra en la propia aplicación, no en otra parte de la pila. Puede que no le guste tener que especificar el conjunto de caracteres de su base de datos en PHP, pero si lo piensa, realmente es a donde pertenece, porque también es donde está especificando la base de datos a la que desea conectarse: es un parámetro de conexión. no es un problema de configuración del servidor. Codificar el conjunto de caracteres en cualquier otro lugar hace que su aplicación no sea portátil.