Foros del Web » Programando para Internet » PHP »

comportamiento inesperado utf8_spanish_ci

Estas en el tema de comportamiento inesperado utf8_spanish_ci en el foro de PHP en Foros del Web. Buenas. Mirando sobre el tema de los character sets y collations he leído que en mysql collation utf8_spanish_ci no distingue entre vocales con tilde o ...
  #1 (permalink)  
Antiguo 16/09/2013, 13:18
 
Fecha de Ingreso: julio-2006
Ubicación: Barcelona
Mensajes: 244
Antigüedad: 17 años, 9 meses
Puntos: 32
comportamiento inesperado utf8_spanish_ci

Buenas.

Mirando sobre el tema de los character sets y collations he leído que en mysql collation utf8_spanish_ci no distingue entre vocales con tilde o sin tilde. Sin embargo, a mi me está ocurriendo lo contrario y me gustaría averiguar por qué. Así que os presento un pequeño código que he hecho para intentar descubrir por qué razón no se comporta adecuadamente.

Primeramente quería recordar que en utf8 el carácter "o" equivale a x6F o 111 y el carácter "ó" equivale a xc3 b3 o 195 179.

Bien, pues el código que voy a exponer trata de insertar en una tabla el texto "camión"(con tilde) y luego comprobar si existe alguna palabra en la tabla que contenga "camion"(sin tilde)

Para ello he creado la base de datos asignándole el character set y collation:
Código MySQL:
Ver original
  1. create database if not exists dbase character set utf8 collate utf8_spanish_ci;
Luego creo la tabla de nombre texto:
Código MySQL:
Ver original
  1. create table dbase.texto ( texto varchar(10) not null );
Creo privilegios para esa base de datos para un usuario de nombre "user" y contraseña "1234":
Código MySQL:
Ver original
  1. grant all on dbase.* to 'user'@'%' identified by '1234';

Luego creo el código php y lo guardo en formato utf-8:
Código PHP:
<?php

    
function connect_db()
    {
        
$db_link = new mysqli"localhost""user""1234""dbase" );
        
// comprobar que la conexión se efectúe
        
if( $db_link->connect_errno )
        {
            echo 
"Conexion fallida: ".$db_link->connect_error;
            exit();
        }
        return 
$db_link;
    }

    function 
select$texto )
    {
        
$db_link connect_db();

        
$result 
            
$db_link->query
                
"select * from dbase.texto where texto like '%".addslashes($texto).
                
"%' " 
            
);

        
// comprobar que la consulta se efectúe
        
if( $result === false )
        {
            echo 
"select error: ".$db_link->error "<br/>";
            exit();
        }

        
// si la seleccion no es vacia, guardar el primer elemento
        
if( $result->num_rows )
        {
            
$row  $result->fetch_assoc();
            
$word $row["texto"];
        }
        
// en caso contrario guardar false
        
else
            
$word  false;
        
$db_link->close();
        
//retornar el valor
        
return $word;
    }

    function 
insert$texto )
    {
        
$db_link connect_db();

        
$result $db_link->query"insert into dbase.texto values('".$texto."')" );

        
// comprobar que la inserción se efectúe
        
if( $result === false )
        {
            echo 
"insert error: " $db_link->error "<br/>";
            exit();
        }

        
$db_link->close();

    }


    
//-------------------------

    
header('Content-Type: text/html; charset=UTF-8');

    
// insertar camión(con acento) en base de datos
    
insert"camión" );

    
// mostrar palabra camion(sin acento) y su codigo
    
$word "camion";
    echo 
"palabra buscada: $word<br/>codigo: ";
    
$len strlen$word );
    for( 
$i 0$i $len; ++$i )
        echo 
ord$word[$i] ) . " ";
    echo 
"<br/><br/>";

    
// buscar palabra en la base de datos
    
$texto select$word );

    
// Si se encuentra la palabra, mostrarla
    
if( $texto !== false )
    {
        echo 
"Palabra encontrada: \"" $texto "\"<br/>código: ";

        
$len strlen$texto );
        for( 
$i 0$i $len; ++$i )
            echo 
ord$texto[$i] ) . " ";
    }
    else
    {
        echo 
"Palabra no encontrada";
    }

?>
Pues bien, al ejecutar este código, como decía al inicio, no encuentra la palabra "camión", que en principio debería ser equivalente a "camion".

Código:
La salida es la siguiente:
palabra buscada: camion
codigo: 99 97 109 105 111 110 

Palabra no encontrada
Sin embargo, si cambio la linea:
Código PHP:
    $word "camion"
por
Código PHP:
    $word "camión"
Si me encuentra la palabra y la salida es:
Código:
palabra buscada: camión
codigo: 99 97 109 105 195 179 110 

Palabra encontrada: "camión"
código: 99 97 109 105 195 179 110
Como se puede apreciar, tanto la palabra de búsqueda como la que está insertada en la base de datos estan en utf-8. Pues se puede apreciar la secuencia 195 179 correspondiente al código de "ó" en utf-8.

¿Qué está pasando entonces?

Un saludo y gracias!
  #2 (permalink)  
Antiguo 16/09/2013, 13:47
Avatar de jonni09lo
Colaborador
 
Fecha de Ingreso: septiembre-2011
Ubicación: Estigia
Mensajes: 1.471
Antigüedad: 12 años, 7 meses
Puntos: 397
Respuesta: comportamiento inesperado utf8_spanish_ci

Hola, yo siempre he usado es el utf8_general_ci para hacer lo que mencionas (reconocer palabras con o sin acentos)

Saludos
__________________
Haz preguntas inteligentes-Como ser Hacker
No hacer preguntas por mensaje privado. No sólo no es inteligente sino que es egoísta.
  #3 (permalink)  
Antiguo 16/09/2013, 14:05
 
Fecha de Ingreso: julio-2006
Ubicación: Barcelona
Mensajes: 244
Antigüedad: 17 años, 9 meses
Puntos: 32
Respuesta: comportamiento inesperado utf8_spanish_ci

Cita:
Iniciado por jonni09lo
Hola, yo siempre he usado es el utf8_general_ci para hacer lo que mencionas (reconocer palabras con o sin acentos)
Bueno, pues he probado con utf8_general_ci y no soluciono el problema.

Específicamente he borrado la base de datos y la he vuelto a crear así:
Código MySQL:
Ver original
  1. create database if not exists dbase character set utf8 collate utf8_general_ci;
He seguido con el resto de pasos que he descrito antes y me da las mismas salidas.

Si alguien está dispuesto a probar el código y decirme el comportamiento que le da, se lo agradecería. A ver si así puedo localizar el problema.

Un saludo!
  #4 (permalink)  
Antiguo 16/09/2013, 14:10
Avatar de jonni09lo
Colaborador
 
Fecha de Ingreso: septiembre-2011
Ubicación: Estigia
Mensajes: 1.471
Antigüedad: 12 años, 7 meses
Puntos: 397
Respuesta: comportamiento inesperado utf8_spanish_ci

Hola, las tablas de tu base de datos que charset tienen? ya que se me hace extraño...

Saludos
__________________
Haz preguntas inteligentes-Como ser Hacker
No hacer preguntas por mensaje privado. No sólo no es inteligente sino que es egoísta.
  #5 (permalink)  
Antiguo 16/09/2013, 14:21
 
Fecha de Ingreso: julio-2006
Ubicación: Barcelona
Mensajes: 244
Antigüedad: 17 años, 9 meses
Puntos: 32
Respuesta: comportamiento inesperado utf8_spanish_ci

He escrito paso por paso como creo la base de datos, y la tabla, en el primer post.

El character set y collate se los doy a la base de datos. La tabla en teoria los debería heredar.

Un saludo!
  #6 (permalink)  
Antiguo 16/09/2013, 14:37
Avatar de jonni09lo
Colaborador
 
Fecha de Ingreso: septiembre-2011
Ubicación: Estigia
Mensajes: 1.471
Antigüedad: 12 años, 7 meses
Puntos: 397
Respuesta: comportamiento inesperado utf8_spanish_ci

Precisamente por esa razón te pregunte, ya que veo que no lo especificas:

Código SQL:
Ver original
  1. CREATE TABLE dbase.texto ( texto VARCHAR(10) NOT NULL );

Te preguntaba ya que como ser humano se pueden cometer errores (todo es relativo y más en programación)

Que versión de mysql estas usando?

Puedes probar también con utf8_unicode_ci y te recomiendo leer esto

Por ultimo puedes usar set_charset

Saludos
__________________
Haz preguntas inteligentes-Como ser Hacker
No hacer preguntas por mensaje privado. No sólo no es inteligente sino que es egoísta.
  #7 (permalink)  
Antiguo 16/09/2013, 15:05
 
Fecha de Ingreso: julio-2006
Ubicación: Barcelona
Mensajes: 244
Antigüedad: 17 años, 9 meses
Puntos: 32
Respuesta: comportamiento inesperado utf8_spanish_ci

Mi versión es la 5.5.32
según pone aquí:
Código:
$ mysql -u root -p
Enter password: 
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 1567
Server version: 5.5.32-0ubuntu0.12.04.1 (Ubuntu)

Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
Cita:
Iniciado por jonni09lo
Te preguntaba ya que como ser humano se pueden cometer errores (todo es relativo y más en programación)
Lo he probado varias veces depurando hasta donde he sabido para localizar el error. Después cuando escribía el post lo he vuelto a probar vigilando bien cada paso, por esas cosas de no hacer el ridículo más de lo necesario. Ahora lo he probado con collate utf8_unicode_ci y también diferencia vocales con y sin tilde.

Ahora he cambiado la función connect_db del codigo añadiendole el metodo set_charset:
Código PHP:
    function connect_db()
    {
        
$db_link = new mysqli"localhost""user""1234""dbase" );
        
// comprobar que la conexión se efectúe
        
if( $db_link->connect_errno )
        {
            echo 
"Conexion fallida: ".$db_link->connect_error;
            exit();
        }
        
$db_link->set_charset"utf8" );
        return 
$db_link;
    } 
Y ya tiene el comoportamiento que debería tener. De todos modos, no entiendo por qué es necesario ese método si cuando creo la base de datos ya le doy el charset adecuado.

Sobre las diferencias entre utf8_unicode_ci y utf8_general_ci ya había leído algo pero tampoco le había prestado demasiado atención pues problema surgía con algunas comparaciones de caracteres que no tenían que ver con los latinos.

Un saludo y gracias!
  #8 (permalink)  
Antiguo 16/09/2013, 15:11
Avatar de jonni09lo
Colaborador
 
Fecha de Ingreso: septiembre-2011
Ubicación: Estigia
Mensajes: 1.471
Antigüedad: 12 años, 7 meses
Puntos: 397
Respuesta: comportamiento inesperado utf8_spanish_ci

Lastimosamente mi conocimiento no es tan profundo sobre este tema, pero encontre esta información que podría ser de utilidad

Saludos
__________________
Haz preguntas inteligentes-Como ser Hacker
No hacer preguntas por mensaje privado. No sólo no es inteligente sino que es egoísta.

Etiquetas: comportamiento, html, mysql, select, tabla
Atención: Estás leyendo un tema que no tiene actividad desde hace más de 6 MESES, te recomendamos abrir un Nuevo tema en lugar de responder al actual.
Respuesta




La zona horaria es GMT -6. Ahora son las 07:34.