2011-07-06 31 views
10

Estoy modificando una plantilla de wordpress y tengo curiosidad sobre cómo esta es una estructura de control válida en PHP. Alguien tiene alguna idea?¿Cómo es este código php válido?

<?php if(condition): ?> 
<?php if(!condition || !function()) ?> 
<?php elseif(condition): ?> 
<?php if(!condition || !function()) ?> 
<?php endif; ?> 

Si quito todas las etiquetas, consigo (con muesca más en su sano juicio):

<?php 
if(condition): 
    if(!condition || !function()) 
elseif(condition): 
    if(!condition || !function()) 
endif; 
?> 

nulo por las declaraciones if sangría no terminan. Entonces, ¿cómo/por qué es este código válido si hay apertura y cierre de etiquetas php en todas partes?


Editar para kerrek SB. Haga un archivo php y ejecútelo. Es válido:

<?php if(true): ?> 
<?php if(true) ?> 
<?php endif; ?> 
<?php echo 'here'; ?> 
+3

Rechazo que esto sea válido. ¿Lo has ejecutado con éxito? Errores en y todo? –

+0

@Kerrek SB - Sí, lo probé. Es válido, no tengo idea de por qué. –

+0

@cwolves: Yo también lo hice, y obtuve 'Parse error: error de sintaxis, inesperado T_ELSEIF' ... Déjame probar tu nuevo ejemplo. Además, ¿puedes convertirlo en código real, por favor, no pseudocódigo? –

Respuesta

4

Tu (reducida) código de ejemplo es equivalente a esto:

<?php 
if(condition): 
    if(!condition || !function()) { } 
endif; 
?> 

O incluso:

<?php 
if(condition): 
    if(!condition || !function()); 
endif; 
?> 

Al cerrar la etiqueta <?php, que parecen tener una "declaración vacía " gratis.

Su ejemplo real podría ser de una sola alineado de esta manera:

<?php if(true): if(true); endif; echo 'here'; ?> 

Pero tenga en cuenta que un elseif hace que este ambiguo!

<?php 
if(condition): 
    if(!condition || !function()); 
elseif(condition): // Bogus! which block does this belong to? 
    if(!condition || !function()); 
endif; 
?> 

Tendríamos que eliminar la ambigüedad de esto:

<?php 
if(condition): 
{ 
    if(!condition || !function()); 
} 
elseif(condition): 
{ 
    if(!condition || !function()); 
} 
endif; 
?> 

Ahora está claro, pero ahora nos habríamos ahorrado la sintaxis de colon completo.

¡Gracias a Lekensteyn por señalar esto!

Consulte la explicación a continuación para ver más rarezas.

+0

No es completamente cierto, tome este caso: ' '(error de sintaxis) vs' XXX '(nota el' XXX'). No estoy seguro de si esto es un error o una característica. – Lekensteyn

+0

Gracias por resolver esto. Habla sobre abusar de tu caso marginal :) –

+2

@Lekensteyn - ARGH! –

2

Su código no funcionará debido a que PHP elimina un solo salto de línea después de ?> si existe. ?>[newline]<?php sería el mismo que ?><?php

Algo así como el siguiente tendría más sentido (function sustituye por fn desde function es una palabra clave;)):

<?php if(condition): ?> 
<?php if(!condition || !fn()) ?> 
some 
<?php elseif(condition): ?> 
<?php if(!condition || !fn()) ?> 
thing 
<?php endif; ?> 

que sería interpretado como:

<?php 
if(condition): 
    if(!condition || !fn()) echo "some"; 
elseif(condition): 
    if(!condition || !fn()) echo "thing"; 
endif; 
?> 

Tenga en cuenta que no hay : en dos IFS, los tratará como a un if la que esperan un cuerpo al lado de él. Escrito en una otra manera:

<?php 
if (condition) { 
    if (!condition || !fn()) { 
     echo "some"; 
    } 
} else if (condition) { 
    if (!condition || !fn()) { 
     echo "thing"; 
    } 
} 
?> 
+0

excepto que funciona :) –

+0

"function" dooh, lo encontré mientras mejoraba la respuesta :) – Lekensteyn

+0

ahh, sí lo siento. Solo me refiero a una función genérica :) –

-1

Salida de PHP.net explaination

+1

Obtengo lo que 'if:' hace, mi pregunta es por qué las declaraciones if anidadas no arrojan errores –

0

Si no está utilizando lo que necesita hacer un seguimiento con: para la lógica después anidado si (s).

<?php 
    function foobar() { 
      return true; 
    } 
    function bar() { 
      return false; 
    } 

    $foobar = true; 
    $bar = false; 

    if($foobar): 
     if(!$bar || !foobar()): 
      echo 'foobar'; 
     endif; 
    elseif($bar):  
     if(!$foobar || !bar()): 
      echo 'bar'; 
     endif; 
    endif; 
0

"que no es válida porque la sangría si las declaraciones no terminan"

Sí lo hacen. Como se indica en php.net, la mezcla de ambas notación no es compatible, lo que significa que tiene un nuevo bloque de código (los dos if() sin seguir el doble punto) dentro de su if():, elseif(): y endif;.

if(condition): 
    if(!condition || !function()) 
     // do nothing here, end of first inner if 
elseif(condition): 
    if(!condition || !function()) 
     // also do nothing here, end of second inner if 
endif; // end of outer if/else 
0

which is invalid because the indented if statements don't end

De hecho, lo hacen. El ?> termina la declaración como cualquier otro, por lo que:

<?php 
if(condition): 
    if(!condition || !function()); 
elseif(condition): 
    if(!condition || !function()); 
endif; 
?> 

Si no fuera el caso, entonces lo siguiente sería también un error de sintaxis:

Lol <?php echo "cakes" ?> extravaganza <?php echo "innit" ?> 
0

Lo que veo es que usted está mezclando hasta las dos formas posibles de construir una construcción 'if' en php.

La primera forma es o bien:

if (condition) instruction; 

if (condition) { more; than; one; instructions; } 

El segundo es:

if (condition): instruction; another; endif; 

Cuando se escribe

<?php if (condition) ?> 

... y sin un '{' o un " : 'antes del cierre'?> 'etiqueta, de hecho está truncando el comando if omitiendo las instrucciones, y PHP lo acepta. Cuando vuelva a abrir la etiqueta php, ya estará fuera del if.

Lo mismo NO se aplica si simplemente "olvida" las instrucciones en un solo bloque, donde un 'endif;' no está permitido como una instrucción;

Así:

<?php if (condition) ?> 
anything outside the if 
<?php instruction_outside_the_if; ?> 

... no tiene sentido (porque elaborar un caso, pero no hace nada después de él), pero no es un error estricta.

<?php if (condition 1): ?> <!-- note the ':' in this if --> 
<?php if (condition 2) ?> 
anything outside the second if but inside the first 
<?php endif; ?> <!-- this closes the first if 

... aquí se tiene una primera si funciona, pero el segundo es aún vacía.

<?php if (condition 1): ?> <!-- note the ':' in this if --> 
<?php if (condition 2) ?> 
anything outside the second if but inside the first 
<?php else: ?> 
still outside the second if but inside the first, in the ELSE part 
<?php endif; ?> <!-- this closes the first if 

... esto es más o menos como su ejemplo, cuando la persona (o elseif) pertenece al primer caso.


<?php if (true) ?> 
<?php elseif(foo){ }; ?> 

Esa es otra excepción, ya que no está poniendo nada entre una etiqueta de cierre y la etiqueta de apertura, por lo que el analizador "optimiza" hacia fuera (no es exactamente así, pero es una aproximación correcta) . Trate de poner nada entre las dos etiquetas php, como:

<?php if (true) ?> 
anything 
<?php elseif(foo){ }; ?> 

...y ver aparecer el "error de sintaxis, inesperado T_ELSEIF".

Cuestiones relacionadas