La función empty de PHP está mal

Cuando te pasas 20 minutos depurando código (por cierto, que gran herramienta los debuggers), y descubres que el bug que se manifiesta en A no viene ni de A, ni de B, ni de C, si no de mucho más lejos, más tirando a Z, te das cuenta, como otras tantas veces, la de efectos colaterales que puede tener un “bug” en un sitio remoto.

El caso es que después de 20 minutos he descubierto un bug en una web en PHP que estoy haciendo, y cuando me he dado cuenta de que era un problema de concepto de lo que se supone que hace la función “empty” y lo que realmente hace (tal y como dice en la especificación), pues me he dicho, ui, va a ser que es un bug, pero la implementación de empty no debería ser la que es. No es que quiera llevar la razón en todo, y pensar que los bugs no son culpa mía, obviamente lo son, incluso este, pero hay que tener en cuenta que cuando reconozco que un bug es mi culpa no hago un post sobre ello.

A ver, el caso es el siguiente, en un sitio remoto tenía un condicional, en plan si empty ($str) haz X, y si no es empty, pues haz Y. Fácil.

El problema conceptual viene en que según el manual de PHP: empty(“0″) es true!!

Por el amor de Dios! ¿en que estaría pensando el programador que hizo eso?

No lo digo por decir, lo digo porque no es muy consecuente con la definición del propio manual:

emptyDetermine whether a variable is empty

The following things are considered to be empty:

  • “” (an empty string)
  • 0 (0 as an integer)
  • “0″ (0 as a string)
  • NULL
  • FALSE
  • array() (an empty array)
  • var $var; (a variable declared, but without a value in a class)

Entiendo entonces, que una variable NULL se considere como vacía, que un array() se considere como vacio, que la cadena se considere como vacía, que el valor FALSE se considere como vacío. Incluso entiendo que el número 0 se considere como vacío. Hasta aquí tiene sentido, tiene sentido que cada tipo de datos (booleano, cadena, array, referencia) tenga un único valor que se considere como vacío.

Lo que no entiendo es porqué las cadenas tienen dos valores que se consideran vacías, una cadena vacía es y ya está.

Imagino que la explicación de por qué “0″ es considerado como vacío viene a ser porque en PHP puedes hacer 322 + “17″ e internamente transforma la cadena “17″ en el número 17 y hace la suma numérica. Siguiendo esta premisa, cuando empty recive “0″ a priori no se puede diferenciar si el programador está pasando una cadena porque quiere o el programador pretendía pasar el número 0 pero se le ha olvidado hacer un cast a int.

Conclusión: la función empty debería devolver false con ‘0′, pues asumir que el programador puede estar queriendo pasar 0 en vez de “0″ es imponer una restricción al programador, se le debería dejar que hiciera un cast si es que es un número lo que está evaluando con el empty, al no hacerlo lo que se consigue es que paguen justos por pecadores… argh!!!!

Trackback URL

15 Comments on "La función empty de PHP está mal"

  1. Alejandro Morales Meza
    05/05/2010 at 11:45 am Permalink

    Hola! Creo que la lógica del asunto está en que PHP es un lenguaje no tipado, y al pasar “0″ a la construcción del lenguaje “empty” el no puede hacer diferencia entre “0″ y 0. Esta es la razón por la que para ambos casos el resultado es TRUE.

  2. Pau Sanchez
    06/05/2010 at 12:18 am Permalink

    @Alejandro, PHP es no tipado, efectivamente, pero el significado de “0″ y de 0 es totalmente distinto. Sea tipado, o no tipado.

    Precisamente porque es un lenguaje no tipado, puedes preguntar de que tipo es la variable, y si es un string, considerarlo como cadena no vacia (puesto que no lo es), pero si es un 0 numérico, entonces considerarlo vacio.

    Para mi, está mal el concepto. “0″ no es una cadena vacia, es una cadena con el caracter ‘0′. Si quieres que se interprete como un entero, entonces debería ser problema del programador.

    Te pongo un ejemplo, si la función empty funcionara como describí en este artículo, entonces, lo lógico para alquien que quisiera usar empty tal cual funciona ahora, es hacer un cast a entero primero, y luego preguntar si está vacio. Y ya está, todo sería coherente.

    Saludos!

  3. Alejandro Morales Meza
    28/05/2010 at 2:22 pm Permalink

    Hola Amigo.

    Tiene sentido lo que dices. Estuve probando algunas cosas y me parecio curioso que para empty(), la cadena “0″ es vacío, pero la cadena “00″ no lo es. ¿Qué piensas al respecto?

  4. Pau Sanchez
    28/05/2010 at 11:18 pm Permalink

    @Alejandro Básicamente los programadores de PHP pensaron en implementar empty para que cazara los “0″ como empty, imagino que para facilitarles la vida a algunos programadores… Esa implementación es totalmente intencional, y me parece que tomaron una mala decisión, ya que como he dicho y repetido varias veces, una cadena que tiene un caracter, sea cual sea ese caracter, no es una cadena vacia.

    Obviamente “00″ no tiene que ser vacía, y ellos sólo interpretan como vacía la cadena ‘0′.

Hi Stranger, leave a comment:

ALLOWED XHTML TAGS:

<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre lang="" line="" escaped="">

Subscribe to Comments