¿Qué factores hacen que PHP Unicode sea incompatible?


Puedo usar caracteres UTF-8 muy bien en mis scripts.

De hecho, es posible tener nombres de variables y funciones que contengan caracteres Unicode.

También existe la extensión mb_string que trata con cadenas multi-byte, sin embargo, en innumerables artículos PHP es criticado por su falta de soporte Unicode.

No lo entiendo; ¿por qué se dice que PHP no soporta Unicode?

 38
Author: Leigh, 2009-02-21

7 answers

Cuando PHP se inició hace varios años, UTF-8 no estaba realmente soportado. Estamos hablando de una época en la que el sistema operativo no Unicode como Windows 98 / Me seguía siendo actual y cuando otros grandes lenguajes como Delphi también eran no Unicode. No todos los idiomas fueron diseñados con Unicode en mente desde el día 1, y cambiar completamente tu idioma a Unicode sin romper muchas cosas es difícil. Delphi solo se hizo compatible con Unicode hace un año o dos, por ejemplo, mientras que otros lenguajes como Java o C# eran diseñado en Unicode desde el Día 1.

Así que cuando PHP creció y se convirtió en PHP 3, PHP 4 y ahora PHP 5, simplemente nadie decidió agregar Unicode. ¿Por qué? Presumiblemente para mantener compatible con scripts existentes o porque utf8_de / encode y mb_string ya existían y funcionan. No estoy seguro, pero creo que tiene algo que ver con el crecimiento orgánico. Las características no existen simplemente por defecto, tienen que ser escritas por alguien, y eso simplemente no sucedió para PHP todavía.

Editar: Ok, He leído mal la pregunta. La pregunta es: ¿Cómo se almacenan internamente las cadenas? Si escribo "Währung" o "Écriture", ¿qué Codificación se utiliza para crear los bytes utilizados? En el caso de PHP, es ASCII con una página de código. Eso significa: Si codifico la cadena usando ISO-8859-15 y la decodificas con alguna página de código chino, obtendrás resultados extraños. La alternativa está en lenguajes como C # o Java donde todo se almacena como Unicode, lo que significa: Ya no hay página de código, y teóricamente no se puede lárgate. Recomiendo El artículo de Joel sobre Unicode y Conjuntos de Caracteres, pero esencialmente se reduce a: Cómo se almacenan las cadenas internamente, y la respuesta con PHP es "No en Unicode", lo que significa que debe ser muy cuidadoso y explícito al procesar cadenas para asegurarse de mantener siempre la cadena en la codificación adecuada durante la entrada, el almacenamiento (base de datos) y la salida, lo que es muy errorrone.

 39
Author: Michael Stum,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-12-11 12:49:14

Creo que es en gran medida una dificultad cultural, no técnica.

En cuanto a los problemas técnicos---y no es francamente trivial implementar unicode en un ecosistema construido sobre las suposiciones de que 'un carácter es igual a un byte'---los desarrolladores podrían haber copiado gran parte de los esfuerzos de java o python (este último con una compatibilidad decente y en gran medida de trabajo unicode desde alrededor de 2001), pero nunca lo hicieron.

Cuando leo el hilo de discusión adjunto a la documentación oficial, actual para la función utf8_encode() de php, tengo una sensación de vértigo.

En primer lugar, esa función se llama utf8_encode(); sin embargo, la documentación indica que se espera que la cadena que espera esté en ISO-8859-1 (también conocido como latín-1). eso es tan php, tan 80.

La mayoría de los comentaristas parecen percibir unicode como una carga. hay muchas propuestas de cómo convertir cadenas 'de contenido desconocido', cómo tratar con s'strings con codificaciones mixtas '(wtf?), o tratar con puntos de código que normalmente causan rotura porque están más allá del límite de cuatro bytes por punto de código de esa función.

La discusión se centra en las correcciones para deshacerse de garabatos o para evitar las partes problemáticas del comportamiento de esa función. y eso, para mí, es tan php: todo el mundo está haciendo correcciones, pocas cosas se implementan de una manera fundamentalmente correcta. si usted cree que esto es una calumnia de mi parte, aquí hay algunas cositas:

Aunque esto parece romper el alemán Umlaute [äöü] si el documento ya es UTF-8.

(falta de comprensión de que utf-8 no está diseñado para funcionar cuando se aplica dos veces)

Mira la función iconv (), que ofrece una forma de convertir de 8859 y dreaded 1252 a UTF8

(buen punto: negligencia del estado de la técnica por parte de los desarrolladores de php; en su lugar, implementación propia con errores)

Uso de preg_match para detectar si se necesita utf8_encode [...] excluidas las madres sustitutas [...] excluir overlongs

(sugiriendo borrar silenciosamente todo el contenido problemático de las cadenas, dejando solo aquellas cosas que no se rompen utf8_encode(); esto puede hacer que los textos sean ilegibles (o desaparezcan por completo), pero bueno, no más mensajes de error)

Codificar una cadena solo si todavía no es UTF-8 [...] mb_detect_encoding($s, "UTF-8")

(como señaló otro comentarista , esto no va a funcionar:

$str = 'áéóú'; // ISO-8859-1
mb_detect_encoding($str, 'UTF-8'); // 'UTF-8'
mb_detect_encoding($str, 'UTF-8', true); // false

Así que aquí estamos viendo un error siendo reemplazado por otro. feliz caza. además, lo que parecen proponer aquí es resolver un problema utilizando medios heurísticos (lentos, inciertos) que podrían y deberían resolverse con medios mecánicos (rápidos, ciertos)

Utf8_ [encode / decode] también traducirá caracteres de windows-1252, no solo de / a ISO-8859-1 como dice la documentación

(nunca puede confiar en la documentación oficial de php para ser clara o exhaustiva - - - siempre debe leer a través de años de experiencia de los usuarios que nadie responderá a los documentos)

He estado trabajando en una función is_utf8 y quería publicarla aquí, además de otras también tomé en consideración el error de 5000 char

(una solución para un problema que en gran parte solo existe porque unicode no está implementado correctamente. también aprendemos que la función utf8_encode() no solo renunciará a más de 4 bytes por punto de código, sino que también se romperá si el resultado (o la salida?) el texto excede un límite de 5000 caracteres)

I podría seguir así. ya tienes la idea: a juzgar por este hilo, la comunidad php simplemente no suena como si estuvieran en cualquier lugar listos para comprender de qué se tratan las codificaciones y los conjuntos de caracteres, lo que se necesita para construir una infraestructura de sonido en general o, específicamente, para implementar unicode de una manera adecuada. en su lugar, están usando sus andamios, sus cartones, sus clavos y martillos y siguen construyendo este gran edificio llamado php, lanzando su cinta adhesiva a cada problema eso no se puede deshacer con otro clavo. por supuesto, ese edificio sufrirá de cada viento que venga soplando, como el carácter legal pero inesperado ocasional.

Ver este hilo en particular activo durante ocho años no infunde exactamente confianza en que la situación va a ser mejor en ocho años a partir de ahora.

 33
Author: flow,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-04-30 06:11:23

El concepto de un "carácter multibyte" está en el centro del problema.

  1. Filtra un detalle de implementación: debería ser capaz de trabajar con la abstracción de un carácter sin saber cómo los implementadores eligen representar los datos - tal vez dependiendo de la plataforma les convenga representar todo como UTF16 o UTF32, en cuyo caso todo es multibyte, no es que a los usuarios de la abstracción de caracteres les importe.
  2. Es un kludge: Encima de un anticuado hábito de pensamiento donde todos "realmente sabemos" que las cadenas son secuencias de bytes, ahora tenemos que saber que a veces los bytes se agrupan en cosas conocidas como caracteres Unicode, y tienen casos especiales por todas partes para lidiar con ello.
  3. Es como un ratón tratando de comer un elefante. Al enmarcar Unicode como una extensión de ASCII (tenemos cadenas normales y tenemos mb_strings), hace las cosas mal, y se cuelga en qué casos especiales se requieren para tratar con los caracteres con garabatos divertidos que necesitan más de un byte. Si considera que Unicode proporciona un espacio abstracto para cualquier carácter que necesite, ASCII se acomoda en eso sin necesidad de tratarlo como un caso especial.
 11
Author: ,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-02-26 18:12:26

Usted mismo lo dice: para tratar correctamente con cadenas que contienen caracteres multibyte, necesita usar una extensión. Olvídese de cualquier lugar para usar las funciones de extensión en lugar de las más familiares "normales", y sus datos se mutilan. Lo mismo sucede si utiliza una biblioteca de terceros que no se ha actualizado para usar la función de extensión en todas partes.

Además, un número de codificaciones extremadamente populares todavía están explícitamente no soportadas por PHP, probablemente porque es imposible hacerlo y permanecer hacia abajo compatible.

 5
Author: Michael Borgwardt,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-02-21 00:22:18

Muchas de las extensiones comunes no tienen soporte unicode o (peor aún) "necesita saber" que una cadena contiene secuencias unicode/utf-8, como por ejemplo XmlReader. Y puede hacer una gran diferencia si glob() de PHP llama a FindFirstFileA o FindFirstFileW en win32.
Otro problema (mucho más pequeño pero sorprendentemente a menudo es la fuente de molestia) son las BOM que PHP no reconoce.

 3
Author: VolkerK,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-02-21 00:25:55

Muchas de las funciones de cadena son solo envoltorios delgados alrededor de los equivalentes de la biblioteca de C, que también tratan todo como una secuencia de bytes. Otra razón es que PHP lleva consigo una gran cantidad de equipaje innecesario de compatibilidad con versiones anteriores y, por lo tanto, se queda atascado con malas decisiones de diseño de 3 y 4.

Tal vez con los espacios de nombres de la versión 5.3 finalmente tengan una forma de eliminar gradualmente las funciones antiguas.

 3
Author: ,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-02-21 00:28:51

Lo que se entiende por 'soporte' es 'soporte nativo'. Echa un vistazo a this para obtener información detallada.

 2
Author: muratgu,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-02-21 00:06:29