I'm modifying a wordpress template and I'm curious as to how this is a valid control structure in PHP. Anyone have any开发者_Python百科 insight?
<?php if(condition): ?>
<?php if(!condition || !function()) ?>
<?php elseif(condition): ?>
<?php if(!condition || !function()) ?>
<?php endif; ?>
If I remove all the tags, I get (with more sane indentation):
<?php
if(condition):
if(!condition || !function())
elseif(condition):
if(!condition || !function())
endif;
?>
which is invalid because the indented if
statements don't end. So how/why is this code valid if there are opening and closing php tags everywhere?
Edit for Kerrek SB. Make a php file and run it. It's valid:
<?php if(true): ?>
<?php if(true) ?>
<?php endif; ?>
<?php echo 'here'; ?>
Your (reduced) example code is equivalent to this:
<?php
if(condition):
if(!condition || !function()) { }
endif;
?>
Or even:
<?php
if(condition):
if(!condition || !function());
endif;
?>
By closing off the <?php
tag, you appear to get an "empty statement" for free.
Your real example could be one-lined like so:
<?php if(true): if(true); endif; echo 'here'; ?>
But note that an elseif
makes this ambigous!
<?php
if(condition):
if(!condition || !function());
elseif(condition): // Bogus! which block does this belong to?
if(!condition || !function());
endif;
?>
We'd have to disambiguate this:
<?php
if(condition):
{
if(!condition || !function());
}
elseif(condition):
{
if(!condition || !function());
}
endif;
?>
Now it's clear, but now we could have spared ourselves the colon syntax altogether.
Thanks to Lekensteyn for pointing this out!
See the discussion below for further oddities.
Your code won't work because PHP removes a single newline after ?>
if exist. ?>[newline]<?php
would be the same as ?><?php
Something like the below would make more sense (function
replaced by fn
since function
is a keyword ;) ):
<?php if(condition): ?>
<?php if(!condition || !fn()) ?>
some
<?php elseif(condition): ?>
<?php if(!condition || !fn()) ?>
thing
<?php endif; ?>
It'd be interpreted as:
<?php
if(condition):
if(!condition || !fn()) echo "some";
elseif(condition):
if(!condition || !fn()) echo "thing";
endif;
?>
Note that there is no :
on two ifs, those will be treated like an if
which expect a body next to it. Written in an other way:
<?php
if (condition) {
if (!condition || !fn()) {
echo "some";
}
} else if (condition) {
if (!condition || !fn()) {
echo "thing";
}
}
?>
If you are not using you need to follow up with: for logic after nested if(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;
"which is invalid because the indented if statements don't end"
Yes they do. As stated at php.net, the mixing of both notation isn't supported, which means, you have a new code-block (the two if()
without following double point) within your if():
, elseif():
and 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
which is invalid because the indented if statements don't end
Actually, they do. The ?>
terminates the statement like any other, so:
<?php
if(condition):
if(!condition || !function());
elseif(condition):
if(!condition || !function());
endif;
?>
Were this not the case, then the following would also be a syntax error:
Lol <?php echo "cakes" ?> extravaganza <?php echo "innit" ?>
What I see is that you are mixing up the two possible form of building an 'if' construct in php.
The first form is either:
if ( condition ) instruction;
if ( condition ) { more; than; one; instructions; }
The second one is:
if ( condition ): instruction; another; endif;
When you write
<?php if (condition) ?>
...without a '{' or a ':' before the closing '?>' tag, in fact you're truncating the if command omitting the instructions, and PHP accept this. When you'll open the php tag again, you're already outside the if.
The same does NOT apply if you just "forget" the instruction whitin a single block, where an 'endif;' is not allowed as an instruction;
So:
<?php if (condition) ?>
anything outside the if
<?php instruction_outside_the_if; ?>
... is meaningless (because you elaborate an if but do nothing after it) but is not a strict error.
<?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
...here you have a first if that works, but the second is still empty.
<?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
...this is more or less like your example, where the else (or elseif) belongs to the first if.
<?php if (true) ?>
<?php elseif(foo){ }; ?>
That's another exception, as you're not putting anything between a closing tag and opening tag, so the parser "optimizes" them out (is not exactly like that, but it's a correct approximation). Try putting anything between the two php tags, like:
<?php if (true) ?>
anything
<?php elseif(foo){ }; ?>
... and see the "syntax error, unexpected T_ELSEIF" appear.
Check out PHP.net's explaination
精彩评论