2009-07-09 14 views
14

Me he dado cuenta de que, aunque la mayor parte de mi experiencia consiste en escribir aplicaciones PHP, me encuentro cometiendo "errores de principiante" de vez en cuando. Esto porque PHP es un lenguaje que ha crecido de manera muy orgánica y, como tal, tiene algunas peculiaridades, caprichos y trampas que no conozco.peculiaridades y errores de PHP

Me gustaría que esta pregunta sea una wiki para todos aquellos que quieran conocer las trampas y excepciones de PHP de lo que podríamos creer que son las reglas. Pero, por favor, no escriba las respuestas generales como:

Algunas funciones reciben como argumentos $needle, $haystack, mientras que algunos como $haystack, $needle.

Indique los nombres de las funciones. Tienes algunas respuestas mías como ejemplos. Ah, y agrega una trampa por respuesta. De esta forma, veremos cuál es el más despreciado de todos ellos (mediante votación).

No quiero comenzar una guerra de llamas, no se preocupe por el tema. Si desea escribir algunas cosas malas sobre PHP, hágalo como un comentario a la respuesta respectiva.

Esperamos que esta wiki sea de ayuda para todos nosotros, principiantes y expertos.

Actualización:

Después del comentario de Andrew Moore Estoy pensando que la respuesta también debe contener una solución o solución para la trampa.

+0

A partir de php 5.3.3 ya no puede usar el nombre de clase como el nombre del constructor si usa namespaces. Debes usar '__construct'. No se emitirán advertencias, pero al llamar a 'new MyClass' no se ejecutará el código en su constructor. Hurra por un buen escollo. – nus

Respuesta

1

Aunque las cadenas se pueden iterar utilizando los bucles e índices for, no se pueden iterar utilizando los bucles foreach. Ejemplo:

$str = 'foo'; 
$max = strlen($str); 

for ($i=0; $i<$max; $i++) { 
    echo $str[$i]; 
} 
// outputs: foo 

foreach ($str as $char) { 
    echo $char; 
} 
// Warning: Invalid argument supplied for foreach() ... 
+4

foreach (str_split ($ str) AS $ char) {echo $ char; } –

+3

Esto se debe a que las cadenas no son matrices de caracteres en PHP. El bucle for funciona solo porque los corchetes [] son ​​azúcar sintáctico para acceder a un personaje en particular. Desafortunadamente, esto también da la apariencia de que las cadenas se pueden manipular como matrices de caracteres, que como se ve en el ciclo foreach, no es cierto. Como anotó Andrew, usar str_split() es una manera fácil de dividirlo en una matriz real si eso es lo que necesita. –

+0

no tiene nada que ver con la publicación original ... – eddy147

10

objetos Serialización de que las estructuras de proceso de XML y luego revertir la seriación ellos no restaura la estructura original XML:

$dom = new DOMDocument; 
$dom->loadXML('<test/>'); 

$dom = serialize($dom); 
$dom = unserialize($dom); 

var_dump($dom->saveXML()); 
// $ Warning: DOMDocument::saveXML(): Couldn't fetch DOMDocument in ... 
// $ NULL 

mismo modo para los objetos SimpleXML.

8

Preferencia del operador estándar no industrial.

$x = 1; 
echo 'foo: ' . $x+1 . ' bar'; 

salida será: "1 bar", en lugar del esperado "foo: 2 bar". Solución: use paréntesis.

+7

La posibilidad de echo() de tomar varios argumentos se puede usar aquí también: echo 'foo:', $ x + 1, 'bar'; –

+0

Vale la pena señalar que hay * dos * cosas funky sobre esto: no solo la precedencia no es lo que quería, sino que también ("foo: 1" + 1) no concatenan; aparentemente es igual a 1, no "foo: 11". – ojrac

+4

@ojrac, eso es porque el operador de concatenación en PHP es. (punto), no + (más) como en muchos otros idiomas. + se usa para la suma aritmética y "foo: 1" se evalúa a 0 para agregarle 1, por lo que el resultado final es 1. –

7

El tamaño entero depende de la plataforma. Normalmente no puede usar enteros de 64 bits en una máquina de 32 bits sin ningún módulo externo. Además, no puede declarar enteros sin signo.

+0

Para eso es la biblioteca BC. –

1

mi favorito:

<?php 
$a = 0; 
$b = 'x'; 
var_dump(FALSE == $a); 
var_dump($a == $b); 
var_dump($b == TRUE); 

echo' <br />Conclusion: TRUE equals FALSE (at least in PHP)'; 
+2

Esto también se puede mostrar en otros lenguajes de scripting, no solo en PHP. Tiene que ver con cómo 'x' se convierte en un número entero para la comparación. –

+2

El operador == coacciona los tipos de datos. Deberías usar ===, de todos modos. – spoulson

+0

"El operador == coacciona datos ..." no siempre, algunas veces quiero tratar nulo, 0, '' como falso y todo lo demás como verdadero. –

2

Algunas funciones PHP de reciente introducción plano de la caída, porque no hay garantía de que van a ser apoyados por defecto en entornos de alojamiento.

El mayor motivo favorito de la mía es la configuración que permite short_tags<? foobar(); ?> y <?=$var ?> sintaxis etiqueta. Argumento que PHP debería haber habilitado esta función por defecto, en lugar de optar por ella.

EDITAR == ==

En PHP> = 5.4 short_tags el ajuste ya no se toma en cuenta para la declaración de eco abreviada, como tal, estará disponible en todos los entornos de hosting que soporte PHP 5.4 y arriba.

+0

Acepto que las etiquetas cortas deben ser las predeterminadas. – tj111

+7

etiquetas cortas son malvadas. se mezclan con la declaración XML. no deberías usarlo ... –

+2

Irracional. La declaración XML es un caso marginal. Y luego me dirá que las etiquetas cortas son "difíciles de leer" y otras tonterías. En pocas palabras, " spoulson

8

Odio cómo puede obtener problemas si cierra archivos php con una etiqueta de cierre ?> (que parece que debería ser al revés). Por ejemplo, incluya un archivo con algunos espacios en blanco después de?> Y luego intente cambiar los encabezados (suponiendo que no haya memoria de salida). UGH. Me llevó hasta long para aprender a no cerrar los archivos php con ?>

1

== == EDITAR Esto ya no es cierto para PHP> = 5.5!

Lo que a veces encuentro con el error es Fatal error: Can't use function return value in write context cuando se utiliza el constructo empty() . Por ejemplo:

if (!empty(trim($_GET['s']))) { 
    // ... 
} 

empty() necesita una variable, cualquier otra cosa resultará en el error.

La solución:

$s = trim($_GET['s']); 
if (!empty($s)) { 
    // ... 
} 
+1

Aún más simple: 'if (! Trim ($ _ GET ['s'])) {...' – troelskn

4

convenciones de nomenclatura inconsistente de funciones incorporadas. Por ejemplo, este conjunto de funciones de procesamiento de cadenas:

str_shuffle() 
str_split() 
str_word_count() 
strcasecmp() 
strchr() 
strcmp() 

Solución: Deje el manual abierto en todo momento.

+0

Dicho sea de paso, parte de la razón es que inicialmente estaban tratando de emular C con funciones como 'strstr()' y 'strcmp()'. –

0
$x = "a string"; 

if ($x == 142) 
{ 
    echo "lol, of course $x is a number"; 
} 
else 
{ 
    echo "$x is clearly not equal to 142"; 
} 

cuando se ejecuta:

lol, of course a string is a number 

Debe utilizar ===

$x = "a string"; 

if ($x === 142) 
{ 
    echo "lol, of course $x is a number"; 
} 
else 
{ 
    echo "$x is clearly not equal to 142"; 
} 

Cuando se ejecuta:

a string is clearly not equal to 142 
+0

Creo que este ejemplo, aunque común en la comunidad PHP, es de gran ayuda para las personas que provienen de lenguajes de programación estrictos. Algunos de ellos ni siquiera saben que existe el triple igual. –

+0

Sí, me tomó un tiempo depurar este problema en mi código. Sabía que == tipos de datos coaccionados pero no sabía ("una cadena" == 234) se evaluaría como verdadero. – Tyler

+3

lo siento, pero eso no es cierto. "una cadena" == 142 evaluará a falso. ver la tabla de comparación suelta en http://ch.php.net/manual/en/types.comparisons.php –

7

múltiples maneras de hacer las pruebas de la verdad (not operator, empty(), is_null(), isset()) + tipificación débil = this

Con un poco de disciplina se puede sobre todo evitar la necesidad de hacer referencia a esta tabla:

  • Para los ensayos generales de la verdad, se puede usar la comparación booleana if ($) {...} if (!$x) { ... }. Se comporta como lo hacen los operadores booleanos en la mayoría de los lenguajes.

  • Siempre use empty() si desea probar la entrada de formulario para valores de falsy (trata "0" como falso).

  • Siempre use isset() si desea determinar whethere se establece una variable o no

  • Uso is_null() o $x === NULL si sólo tiene que comprobar NULL

6

que he tenido todo tipo de molestar la combinación de foreach con las referencias

$testarray = array(1 => "one", 2 => "two"); 
$item = "three"; 
$testarray[3] =& $item; 
foreach ($testarray as $key => $item) { 
    // do nothing 
} 
echo $testarray[3]; // outputs "two" 

Esto realmente me sorprendió durante la era de PHP4, y aunque ha mejorado en PHP5 al tener un comportamiento sensato si no usas referencias explícitas, aún así logro atraparlo de vez en cuando.

+0

¿Sabes lo que está pasando debajo del capó? Tengo curiosidad por qué php devuelve esto. – Harijoe

+1

La = y asignación hace que la entrada final en la matriz sea una referencia a la variable $ item. En cada iteración del ciclo foreach eso significa que $ testarray [3] cambia para ser el valor actual de $ item. Como $ testarray [2] es "dos", ese valor persiste al iterar sobre $ testarray [3], y sigue siendo el valor final de $ testarray [3] –

2

Las funciones tienen un comportamiento diferente en diferentes sistemas operativos, y algunas funciones solo están disponibles en sistemas operativos específicos.

Por ejemplo, la función mail() en Windows no puede tomar el nombre del remitente en el parámetro $to. Solo puede contener una dirección de correo electrónico. En Linux todo funciona bien.

Otro ejemplo, la función strptime() solo está disponible en Linux, y no en Windows (esto me consiguió en un proyecto existente que quería ejecutar en mi cuadro de Windows).

Claro, hay algunas funciones que solo tienen sentido en ciertos sistemas operativos (como las funciones Win32API), pero muchos otros parecen que deberían comportarse igual en todos los sistemas operativos, cuando en realidad no es así.

+0

La familia 'exec()' es mi favorita en esta categoría. –

2

A veces le gusta pasar directamente un resultado de función a otra función, que solo acepta variables como entrada.

Por ejemplo:

array_pop( explode('\\', get_class($this)) ) 

... se traducirá en una E_STRICT-error "Sólo las variables deben ser pasados ​​por referencia". Para conseguir conseguir que funcione sólo tiene que añadir otro par de soportes alrededor del interior (devuelto) declaración:

array_pop((explode('\\', get_class($this)))) 

(Si su están utilizando espacios de nombres y clases extendidas, esta línea devuelve sólo el nombre de la clase (sin espacio de nombres) de la llamada object-not the parent-class que se extendió y puede contener esta función.)

+0

Acabo de enfrentar este error. Gracias por la solución. Por cierto, PHPStorm no reconoce los corchetes adicionales. PD: Este problema también podría resolverse utilizando el método '\ ReflectionObject' y' getName() '. – Kirzilla

Cuestiones relacionadas