Manipulación de strings de PHP codificadas en UTF-8

Esta semana me he encontrado con un problema que me dió muchos quebraderos de cabeza pero que por suerte llegué a una solución :)
El problema surgía al manipular cadenas de caracteres en php codificadas en UTF-8 con funciones del tipo ucwords, strtoupper, etc...
Al pasarlas por éstas funciones, algunos caracteres se corrompían, y se guardaban erroneamente.

Indagando un poco encontré la explicación a todos éstos problemas.
Las funciones de manipulación de strings en PHP están programadas para trabajar con caracteres de 1 byte de longitud. De ésta manera, funciones como contar el número de caracteres que incluye una cadena (strlen) simplemente calcula el tamaño ocupado en memoria y divide por 1 byte. Todo esto se viene abajo al utilizar cadenas de caracteres codificadas con juegos de caracteres como UTF-8, en los que algunos caracteres pueden ocupar 2 o 3 bytes. Por lo tanto, muchas de las funciones típicas de trabajo con cadenas son peligrosas de usar si nuestros textos están codificados en UTF-8 y son susceptibles de contener éste tipo de caracteres de mayor tamaño, que al leer byte a byte, encontrará erroneamente los datos binarios correspondiente a dos (o tres) caracteres, en vez de uno.

Existe una lista de funciones "inseguras" al trabajar con cadenas con encodings que guarden caracteres de más de 1 byte. Son las siguientes :
· ord
· str_ireplace
· str_pad
· str_split
· strcasecmp
· strcspn
· stristr
· strlen
· strpos
· strrpos
· strrev
· strspn
· strtolower
· strtoupper
· substr_replace
· [l|r]trim (unicamente cuando se usa el segundo parametro)
· ucfirst
· ucwords

Si lo que necesitas es convertir toda la cadena a minúsculas (strtolower), a mayúsculas (strtoupper) o la primera letra de cada palabra a mayúsculas y el resto en minúsculas (ucwords), existe una alternativa que nos evitará tener que cambiar el encoding de nuestra cadena:

PHP:
  1. $string = mb_convert_case($string, TIPO_ACCION, "UTF-8");

Donde TIPO_ACCION  puede tomar los  siguientes valores para obtener el resultado equivalente:  "MB_CASE_LOWER" (strtolower), "MB_CASE_UPPER" (strtoupper)  , "MB_CASE_TITLE" (ucwords)

mb_convert_case es una función que permite la manipulación de los caracteres de una cadena de tipo multibyte.

Tienes muchas más funciones para cadenas multibyte.

Un saludo !

8 Responses

  1. pjosh Apr 08, 2009 -

    Wow… que buen tutorial, está de lujaso!!

  2. Jone Apr 28, 2009 -

    Gracias… llevaba todo el dia intentando solucionarlo, y ha sido esta la solucion!!

  3. fillito Apr 28, 2009 -

    @Jone : Me alegro de que te fuera útil. Un saludo !!

  4. Darksk May 08, 2009 -

    estos son los aportes ke valen la pena esta muy buena tu explicacion

  5. fillito May 09, 2009 -

    @Darksk Gracias por tus palabras.

    Un saludo !

  6. Agustin May 21, 2009 -

    Una aportación increíble! me estaba rompiendo la cabeza! Infinitamente buenas la aportación y la explicación. Que crack!

  7. fillito May 21, 2009 -

    @Agustin : mil gracias a tí por tus palabras. Que fuera útil para todos era la idea. Me alegro de que así sea.

    Un saludo !!

  8. Iñaki Soria Sep 09, 2009 -

    Muy util =)

Leave a Reply