htmlentities() vs. htmlspecialchars(): la batalla del escape en PHP
\n\nSi alguna vez has tenido que mostrar datos de usuarios en una página web, seguro que has oído hablar de las funciones htmlentities() y htmlspecialchars(). Son las dos herramientas principales de PHP para protegerte de ataques XSS y mostrar correctamente los caracteres HTML. Pero, ¿cuál es la diferencia entre ellas? ¿Cuál debería usar un principiante y cuál un experto? Vamos a aclararlo de una vez por todas.
Imagina que estás creando un blog en PHP y un usuario escribe un comentario como este: <script>alert('XSS')</script>. Si lo muestras directamente en pantalla, el navegador ejecutará el script. ¡Un desastre! Aquí es donde entran en juego htmlspecialchars() y htmlentities(). Pero cada una funciona de manera diferente.
¿Qué tienen en común htmlspecialchars() y htmlentities()?
\n\nAmbas funciones convierten caracteres especiales HTML en sus entidades HTML correspondientes. Por ejemplo:
\n- \n
&(ampersand) →&\n <(menor que) →<\n >(mayor que) →>\n "(comilla doble) →"\n '(comilla simple) →'(o'según la bandera) \n
Sin ellas, cualquier entrada con corchetes angulares o ampersands rompería el diseño o abriría la puerta a los hackers.
\n\nLa diferencia clave: el alcance de la conversión
\n\nAquí está el secreto. htmlspecialchars() es un luchador eficiente. Solo convierte los cinco caracteres principales que tienen un significado directo en HTML:
- \n
&→&\n <→<\n >→>\n "→"\n '→'(si se incluye la banderaENT_QUOTES) \n
En cambio, htmlentities() es un perfeccionista. Convierte todos los caracteres para los que existen entidades HTML. Esto incluye no solo los corchetes angulares, sino también símbolos de moneda (€, £, ¥), signos matemáticos (∑, ∂), letras con acentos (é, ñ, ü) e incluso emojis (☺).
Ejemplo práctico: la diferencia en acción
\n\nVeamos el código. Supongamos que tenemos una cadena con texto en francés:
\n\n<?php\n$text = "Café & thé <script>alert('test')</script>";\necho "htmlspecialchars: " . htmlspecialchars($text, ENT_QUOTES, 'UTF-8') . "<br>";\necho "htmlentities: " . htmlentities($text, ENT_QUOTES, 'UTF-8');\n?>\n\nResultado:
\nhtmlspecialchars: Café & thé <script>alert('test')</script>\nhtmlentities: Café & thé <script>alert('test')</script>\n\nEn este ejemplo no hay diferencia, porque los caracteres "é" y otras letras latinas no tienen un significado especial en HTML. Pero probemos con caracteres que sí tienen entidades:
\n\n<?php\n$text = "€ 100 <b>negrita</b>";\necho "htmlspecialchars: " . htmlspecialchars($text, ENT_QUOTES, 'UTF-8') . "<br>";\necho "htmlentities: " . htmlentities($text, ENT_QUOTES, 'UTF-8');\n?>\n\nResultado:
\nhtmlspecialchars: € 100 <b>negrita</b>\nhtmlentities: € 100 <b>negrita</b>\n\n¿Lo ves? htmlentities() convirtió el símbolo del euro "€" en su entidad €. Mientras que htmlspecialchars() lo dejó tal cual. ¿Por qué? Porque "€" no es un carácter peligroso para HTML: el navegador lo muestra correctamente sin necesidad de escaparlo.
¿Cuándo usar htmlspecialchars()?
\n\nEs tu opción por defecto. Usa htmlspecialchars() en el 99% de los casos cuando muestres datos de usuarios en pantalla. Es más rápida, más ligera y cubre todos los caracteres que realmente representan un riesgo de seguridad. Para la mayoría de aplicaciones web, es todo lo que necesitas.