PHP - comportamiento inesperado utf8_spanish_ci

   
Vista:

comportamiento inesperado utf8_spanish_ci

Publicado por jefebrondem (2 intervenciones) el 16/09/2013 21:30:30
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:
1
create database if not exists dbase character set utf8 collate utf8_spanish_ci;
Luego creo la tabla de nombre texto:
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":
1
grant all on dbase.* to 'user'@'%' identified by '1234';

Luego creo el código php y lo guardo en formato utf-8:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
<?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 > 0 )
		{
			$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".

1
2
3
4
5
La salida es la siguiente:
palabra buscada: camion
codigo: 99 97 109 105 111 110
 
Palabra no encontrada

Sin embargo, si cambio la linea:
1
$word = "camion";
por
$word = "camión";
Si me encuentra la palabra y la salida es:
1
2
3
4
5
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![code]
Valora esta pregunta
Me gusta: Está pregunta es útil y esta claraNo me gusta: Está pregunta no esta clara o no es útil
1
Responder

comportamiento inesperado utf8_spanish_ci

Publicado por Mari Carmen (145 intervenciones) el 17/09/2013 22:48:01
Quizá sea muy sencillo. utf8_spanish_ci si hace distinción entre vocales con y sin tilde.
http://collation-charts.org/mysql60/mysql604.utf8_spanish_ci.html
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar