viernes, 20 de enero de 2017

Codificación de caracteres en PHP

Que PHP siempre ha tenido una relación complicada con la codificación de caracteres no debería ser una novedad para nadie, pero que gran parte de esos problemas se derivan de cosas tan nimias como ser poco consecuentes con las configuraciones, tampoco debería sorprender a nadie.

Es muy habitual empezar un desarrollo en PHP y al empezar a mostrar/recibir textos con caracteres más allá del ANSI7 la cosa se empiece a desmadrar y se traduzca en la aparición espontánea de caracteres sustituyendo a acentos y símbolos variados. Además, las funciones de conversión de caracteres utf8_ trabajan cuando menos de una forma curiosa y a veces impredecible (se logra muchísimo más control usando las función iconv). Aparte, suele ocurrir que todo va relativamente bien hasta que se cruza en el camino el acceso bien de lectura, bien de escritura a una base de datos o a ficheros de texto o algo peor (sí, siempre puede haber algo peor).

Ni que decir que ahora mismo el estándar de facto es usar UTF-8 para cualquier desarrollo web, así que vamos a partir de esa base. Dependerá mucho de cómo y de dónde se haya podido hacer la instalación de PHP, pero los valores por defecto del php.ini pueden ser de lo más pintorescos, así que mejor asegurarse de los mismos (no sólo referido a este tema, si no a todos).

Lo mejor siempre es inicializar correctamente la configuración para asegurarnos que PHP trabaje internamente con lo que estamos esperando. Voy a indicar los parámetros a ajustar en el caso de solamente poder tocar el fichero .htaccess, que suele ser un escenario muy habitual cuando hablamos de desarrollo web. Quien tenga acceso al php.ini ya se imaginará como tiene que especificar esos valores.

AddDefaultCharset utf-8
php_value default_charset "UTF-8"
php_value iconv.input_encoding "UTF-8"
php_value iconv.internal_encoding "UTF-8"
php_value iconv.output_encoding "UTF-8"
php_value mbstring.internal_encoding UTF-8
php_value mbstring.http_output UTF-8
php_value mbstring.encoding_translation On
php_value mbstring.func_overload 6 

Y listo, ya está. Ahora internamente nuestro PHP hablará con la codificación que nosotros queramos y no tendremos que estar especificando en cada función que lo permita la codificación para asegurarnos que trabaje en lo que debe.

Como nota adicional, tampoco estará de más forzar la codificación de la salida de datos y que quede bien claro en nuestras páginas web, a través de cosas como

<?php header('Content-Type: text/html; charset=utf-8'); ?>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />