.rpv{MAiN}Móvil

Usando el charset UTF-8 en PHP-MySQL

∞ 16.06.2010
Usando el charset UTF-8 en PHP-MySQL Los charset o `codificación de caracteres` sirven para trasladar el alfabeto `humano` a binario, de forma que la computadora pueda `entender` lo que se está ingresando. Dado que existen muchos lenguajes en la humanidad también existen muchos charsets ideales para cada caso en particular. Cada uno de estos charsets está preparado para soportar mejor cierto tipo de caracteres específicos de cada idioma (chino, español, ruso, etc.) y, a la vez, tienen ciertas limitaciones para con caracteres ajenos, ante este tipo de situación se ideo la estandarización de charsets y se crearon los charsets unicode, del que UTF-8 es parte.

Estos charsets unicode tienen la particularidad de soportar una amplia gama de caracteres de distintos idiomas por lo que se hacen ideales en el uso de aplicaciones web, entre muchos otros casos, por supuesto. Un ejemplo práctico es el uso de caracteres como: ᴥ☻♣ que si te vas a `ver>código fuente` en tu navegador, te darás cuenta que están tal cual y que no son imágenes, en otro tipo de charset hubieran aparecido como: ᴥ☻♣

En este tutorial explicaré como usar el charset UTF-8 en PHP & MySQL así como agregar esta característica a aplicaciones que ya tengas hechas.

NOTA: En el tutorial siguiente se requerirá de un editor de textos que soporte varios tipos de charsets, esencialmente UTF-8, así como conversiones entre tipos de charsets, si no cuentas con uno te recomiendo que descargues el siguiente: NotePad++, porque es un editor que reúne las características de lo se necesitará en este tutorial, es ligero (de ejecutarlo y para bajarlo, apenas si pesa 3.2MB), es gratuito y de código libre.

1. MySQL & UTF-8



Como primer paso debes configurar a MySQL para que trabaje de forma nativa con UTF-8, si tienes acceso al servidor editar el archivo de configuración de MySQL, el my.ini, debes encontrar y editar los siguientes parámetros (o agregarlos):

character-set-server=utf8
collation-server=utf8_unicode_ci
default-character-set=utf8
default-collation=utf8_unicode_ci


*NOTA: Si tienen # al inicio, eliminalo, de lo contrario la configuración es ignorada.

Después de editarlo reinicias a MySQL.

Si no tienes acceso al servidor entonces debes ejecutar una QUERY desde PHP justo después de la conexión (mysql_connect()) y la selección de base de datos (mysql_select_db()):

mysql_query('SET NAMES \'utf8\'');


Las estructuras de tus tablas también tienen que estar en UTF-8, para esto tendrás que agregar el tipo de charset al que aspiramos, o bien cambiarlo si tu tabla tiene otro tipo de charset.

Si tu tabla es:

CREATE TABLE tabla(
	ID int(9) NOT NULL AUTO_INCREMENT,
	campo1 int(15) NOT NULL DEFAULT 0,
	campo2 varchar(100) DEFAULT NULL,
	PRIMARY KEY (ID)
) TYPE=MyISAM;


Entonces AGREGA:

CREATE TABLE tabla(
	ID int(9) NOT NULL AUTO_INCREMENT,
	campo1 int(15) NOT NULL DEFAULT 0,
	campo2 varchar(100) DEFAULT NULL,
	PRIMARY KEY (ID)
) TYPE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci;


Si tiene otro tipo de charset (latin1, por ejemplo) y lo cambias para que quede como en el ejemplo.

2. Convirtiendo bases de datos de distintos charset a UTF-8



Este paso solo es si ya tienes una base de datos de distinto tipo de charset, lo que vas a hacer es un archivo con extensión .sql, el cual va a contener unas QUERY's que, a grandes rasgos, van a crear una tabla gemela (en UTF-8), volcarán los datos de tu tabla original, borrarán tu tabla original, la crearán de nuevo ya con el charset UTF-8, entonces regresarán los datos de la tabla gemela y eliminarán la tabla gemela.

En este ejemplo tomaremos la estructura de la tabla del punto 1 (que también es un ejemplo ) y supondremos que tu tabla se llama `original`, entonces en tu archivo .sql deberás tener las siguientes QUERY's:

-- creamos la tabla `gemela`:
CREATE TABLE gemela(
	ID int(9) NOT NULL AUTO_INCREMENT,
	campo1 int(15) NOT NULL DEFAULT 0,
	campo2 varchar(100) DEFAULT NULL,
	PRIMARY KEY (ID)
) TYPE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci;

-- ahora importamos todos los datos de la tabla `original`
-- en la `gemela`:
INSERT INTO gemela SELECT * FROM original;

-- eliminamos la tabla `original`:
DROP TABLE original;

-- creamos la tabla `original` ya con estructura UTF-8:
CREATE TABLE original(
	ID int(9) NOT NULL AUTO_INCREMENT,
	campo1 int(15) NOT NULL DEFAULT 0,
	campo2 varchar(100) DEFAULT NULL,
	PRIMARY KEY (ID)
) TYPE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci;

-- regresamos todos los datos de la tabla `gemela`
-- en la `original`pero ya en formato utf-8:
INSERT INTO original SELECT * FROM gemela;

-- optimizamos la tabla `original`:
OPTIMIZE TABLE original;

-- eliminamos la tabla `gemela`:
DROP TABLE gemela;


Y una vez finalizado este archivo lo importas con alguna utilería tipo PHPMyAdmin o directamente desde la terminal de comandos de MySQL:

>mysql -h tuhost:puerto -u tunombredeusuario -p tubasededatos<elarchivo.sql


Obviamente, si tienes más de una tabla será el mismo procedimiento para cada una.

3. Archivos PHP/SQL/JS/HTML & UTF-8



Con NotePad++ vas a crear (o convertir) archivos .php, .htm, .js, .sql, etc. en formato UTF-8, te sugiero que uses el tipo `UTF-8 SIN BOM` (el Byte Order Mark es una firma que se incrusta en el encabezado del archivo que indica que es un archivo de tipo unicode), el incluir este BOM puede traerte problemas, algunos viejos navegadores no saben leer la firma (incluso PHP en ocasiones también)... cuando haces includes (incluir un archivo en .php en otro), como está fuera de las etiquetas <?php la marca se imprime, al imprimirse las funciones de encabezados (header) que pudiera haber después ya no funcionan y te dan el famoso mensaje de:

Warning: Cannot modify header information - headers already sent by (output started at ...) in ... on line ...


Así que desde el famoso NotePad++ te vas a menú `Codificación>Convertir a UTF-8 sin BOM`:



Para que te quede:



En todos tus archivos .php, .htm, .sql, .js,etc.
NOTA: cuando no incluyes caracteres especiales (tildes, caracteres ascii, etc.) en dichos archivos NotePad++ guarda el archivo en modo ANSI, en este caso no es necesario usar el formato sugerido.
NOTA 2: que te queden en formato UNIX o WINDOWS es indistinto.

En tus archivos .htm/.html no olvides colocar la etiqueta meta respectiva al charset:

<!-- Si usas XHTML: -->
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />

<!-- Si usas HTML: -->
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">


En los archivos .php también debes agregar header respectivo al charset:

header('Content-type: text/html; charset=utf-8');


4. UTF-8 en PHP & MultiByte String



PHP tiene soporte para UTF-8, sin embargo, siempre se recomienda usar las funciones MultiByte String (documentación oficial) ya que estas son especialmente diseñadas para soportar estos charsets, por tanto mejores opciones que las que se tiene por default.

Algunas funciones básicas que tiene PHP cambian ligeramente cuando se trabaja con UTF-8:

//si antes usabas:
$str=htmlspecialchars($str);
//ahora debes usar:
$str=htmlspecialchars($str,ENT_COMPAT,'UTF-8');

//si antes usabas:
$str=htmlentities($str);
//ahora debes usar:
$str=htmlentities($str,ENT_COMPAT,'UTF-8');

//si antes usabas:
$str=html_entity_decode($str);
//ahora debes usar:
$str=html_entity_decode($str,ENT_COMPAT,'UTF-8');


En cambio, debes sustituir funciones de PHP con las de MultiByte String:

//claro, primero hay que configurar las mbstring:
mb_internal_encoding('UTF-8');

//si antes usabas:
$str=strtolower($str);//minúsculas
//ahora debes usar:
$str=mb_convert_case($str,MB_CASE_LOWER);

//si antes usabas:
$str=strtoupper($str);//mayúsculas
//ahora debes usar:
$str=mb_convert_case($str,MB_CASE_UPPER);

//si antes usabas:
$str=ucwords($str);//Tipo Título
//ahora debes usar:
$str=mb_convert_case($str,MB_CASE_TITLE);

//si antes usabas:
$str=strlen($str);//contar caracteres
//ahora debes usar:
$str=mb_strlen($str);

//si antes usabas:
$str=substr_count($str,$sub);//contar subcadenas repetidas
//ahora debes usar:
$str=mb_substr_count($str,$sub);

//si antes usabas:
$str=substr($str,$ini,$can);//obtener subcadena
//ahora debes usar:
$str=mb_substr($str,$ini,$can);


Esas son las más típicas, pero consulta la gran variedad de funciones que tiene esta librería en su Documentación Oficial.

5. Posibles problemas



A excepción del punto 2, todos los demás puntos son requeridos para que tu aplicación trabaje de forma correcta con el charset UTF-8, si tus tildes siguen sin mostrarse de forma correcta necesitas revisar punto a punto para detectar el error.

Los errores se detectan principalmente en las tildes, en lugar de mostrar:

En alguna ocasión se jugó un mundial de fútbol en México.


se muestra:

En alguna ocasión se jugó un mundial de fútbol en México.


Espero que este tutorial te sirva.
Saludos.
.rpv{FULL}Versión Móvil