2010-04-01 49 views
19

Estaba escribiendo algunas clases PHP comentadas y me encontré con un problema. Mi nombre (para la etiqueta @author) termina con un ș (que es un carácter UTF-8, ... y un nombre extraño, lo sé).UTF-8 firma BOM en archivos PHP

Aunque guardo el archivo como UTF-8, algunos amigos informaron que ven ese personaje totalmente en mal estado (È™). Este problema desaparece al agregar la firma BOM. Pero eso me preocupa un poco, ya que no sé mucho al respecto, excepto por lo que vi en la Wikipedia y en algunas otras preguntas similares aquí en SO.

Sé que agrega algunas cosas al principio del archivo, y por lo que entendí no es tan malo, pero me preocupa porque los únicos escenarios problemáticos que he leído involucran archivos PHP. Y dado que estoy escribiendo clases de PHP para compartirlos, ser 100% compatible es más importante que tener mi nombre en los comentarios.

Pero estoy tratando de entender las implicaciones, ¿debería usarlo sin preocuparme? o hay casos en los que podría causar daño? ¿Cuando?

+0

Tenga en cuenta que hoy me estaba teniendo un problema donde un ' Volomike

+0

Tenga en cuenta también que los valores de sesión no parecen funcionar correctamente en todas las páginas cuando una página tiene este problema de lista de materiales UTF-8. Tuve que usar un editor hexadecimal como ghex en Ubuntu más 'iconv -f utf8 -t ascii old.php> new.php' repetidamente para detectar todos los problemas Unicode, eliminarlos y guardar la página finalmente en ASCII sin errores el comando iconv. Una vez hecho esto, noté que los valores de sesión de las vars mantenían el estado entre las páginas. – Volomike

+0

Parece que cuando se detecta la BOM UTF-8 en un archivo, nunca se envían encabezados que contengan la sesión y, por lo tanto, las variables de sesión entre páginas obtendrán nuevas sesiones en lugar de mantener la misma sesión. – Volomike

Respuesta

23

De hecho, la lista de materiales son datos reales enviados al navegador. El navegador lo ignorará felizmente, pero aún así no puedes enviar encabezados.

Creo que el problema es realmente la configuración del editor de usted y de su amigo. Sin una lista de materiales, el editor de su amigo puede no reconocer automáticamente el archivo como UTF-8. Puede intentar configurar su editor de manera que el editor espere que sea un archivo en UTF-8 (si usa un IDE real como NetBeans, esto puede incluso convertirse en una configuración de proyecto que puede transferir junto con el código).

Una alternativa es intentar algunos trucos: algunos editores intentan determinar la codificación utilizando algunas heurísticas basadas en el texto introducido. Puede intentar iniciar cada archivo con

<?php //Úτƒ-8 encoded 

y tal vez la heurística lo obtendrá. Probablemente hay cosas mejores para poner allí, y puedes buscar qué heurística de detección de codificación son comunes, o simplemente intentar algo :-)

En general, te recomiendo que corrijas la configuración del editor.

Oh, espera, leí mal la última parte: para extender el código a cualquier parte, creo que es más seguro hacer que todos los archivos solo contengan los caracteres inferiores de 7 bits, es decir ASCII simple, o simplemente aceptar que algunas personas con los editores antiguos, vea su nombre escrito gracioso. No hay una manera segura. La lista de materiales es definitivamente mala debido a los encabezados ya enviado cosa. Por otro lado, siempre que solo coloque caracteres UTF-8 en los comentarios, el único impacto de que un editor malinterprete la codificación es que tiene caracteres extraños. Me gustaría escribir correctamente tu nombre y agregar un comentario dirigido a la heurística para que la mayoría de los editores lo obtengan, pero siempre habrá personas que verán caracteres falsos en su lugar.

+2

+1 para la configuración del editor de arreglos. –

+0

Gracias por los consejos. Entendí dónde me encuentro y creo que en lugar de la heurística de detección de codificación, que es un compromiso un tanto extraño, haré la elección decente y solo deletrearé mi nombre con una "s" en lugar de "ş", la mayoría de las posibles los codificadores ni siquiera tienen ese personaje en su idioma de todos modos. ¿Derecha? :) – treznik

+4

Los navegadores no ignoran la lista de materiales. Y estos errores son difíciles de rastrear. Nunca guarde archivos PHP con BOM. – hakre

12

BOM causaría Headers already sent de error, por lo que, no se puede utilizar la lista de materiales en los archivos PHP

+1

first + ve de mí :) –

1

O puede activar el buffer de salida en php.ini, lo que resolverá el problema de "encabezados ya enviados". También es muy importante utilizar el buffer de salida para el rendimiento si su sitio tiene una carga significativa.

8

Esta es una publicación anterior y ya se ha respondido, pero puedo dejar algunos otros recursos que encontré cuando me enfrenté con este problema de BOM.

http://people.w3.org/rishida/utils/bomtester/index.php con esta página puede comprobar si un archivo específico contiene BOM.

También hay una práctica secuencia de comandos que genera todos los archivos con BOM en su directorio actual.

<?php 
function fopen_utf8 ($filename) { 
    $file = @fopen($filename, "r"); 
    $bom = fread($file, 3); 
    if ($bom != b"\xEF\xBB\xBF") 
    { 
     return false; 
    } 
    else 
    { 
     return true; 
    } 
} 

function file_array($path, $exclude = ".|..|design", $recursive = true) { 
    $path = rtrim($path, "/") . "/"; 
    $folder_handle = opendir($path); 
    $exclude_array = explode("|", $exclude); 
    $result = array(); 
    while(false !== ($filename = readdir($folder_handle))) { 
     if(!in_array(strtolower($filename), $exclude_array)) { 
      if(is_dir($path . $filename . "/")) { 
           // Need to include full "path" or it's an infinite loop 
       if($recursive) $result[] = file_array($path . $filename . "/", $exclude, true); 
      } else { 
       if (fopen_utf8($path . $filename)) 
       { 
        //$result[] = $filename; 
        echo ($path . $filename . "<br>"); 
       } 
      } 
     } 
    } 
    return $result; 
} 

$files = file_array("."); 
?> 

me encontré con ese código en php.net

Dreamweaver también ayuda con esto, se le da la opción de guardar el archivo y no incluye el material BOM

Su una respuesta tardía, pero todavía espero que ayude. Adiós

+0

+1 ¡es una secuencia de comandos impresionante! –

+1

El script fopen_utf8() me ayudó a aislar un archivo BOM de un SDK que estaba usando de un proveedor. ¡Muy útil! –

6

Para que lo sepas, hay una opción en php, zend.multibyte, que permite a php leer archivos con BOM sin dar el error Headers already sent.

Desde el archivo php.ini:

; If enabled, scripts may be written in encodings that are incompatible with 
; the scanner. CP936, Big5, CP949 and Shift_JIS are the examples of such 
; encodings. To use this feature, mbstring extension must be enabled. 
; Default: Off 
;zend.multibyte = Off 
3

En PHP, además de las "cabeceras ya ha sido enviada" error, la presencia de una lista de materiales también puede arruinar el código HTML en el navegador de formas más sutiles .

Consulte este link para obtener un resumen del problema.

Cuando esto ocurre, no solo suele haber un espacio notable en la parte superior de la página representada, pero si inspecciona el HTML en Firefox o Chrome, puede observar que la sección de encabezado está vacía y sus elementos parecen estar vacíos. en el cuerpo. Por supuesto, ver la fuente mostrará todo donde debería estar, pero de alguna manera el navegador lo está interpretando mal.

0

BOM es en realidad la forma más eficiente de identificar un archivo UTF-8, y ambos navegadores y estándares modernos respaldan y fomentan el uso de este en cuerpos de respuesta HTTP.

En el caso de los archivos PHP, no es el archivo sino la salida generada que se envía como respuesta, así que obviamente no es una buena idea guardar todos los archivos PHP con la lista de materiales al principio, pero eso no significa que no deba t use la BOM en su respuesta.

Puede, de hecho, inyectar de forma segura el siguiente código justo antes de su declaración de tipo de documento (en caso de que se está generando HTML como respuesta):

<?="\xEF\xBB\xBF"?>

Para más leído: https://www.w3.org/International/questions/qa-byte-order-mark#transcoding