|
php.net | support | documentation | report a bug | advanced search | search howto | statistics | random bug | login |
[2017-08-30 15:31 UTC] jcmarchi at gmail dot com
Description:
------------
When using Block Alternative Syntax for IF statement (if: elseif: else: endif;) a nested "IF" will trigger a PHP EXCEPTION error saying: syntax error, unexpected ':' if it exists immediately BEFORE the "else:" or "elseif".
Test script:
---------------
Example 1:
<?php
$bar = 'bar';
$foo = 'foo';
if (isset($bar)):
if (isset($foo)) echo "Both are set.";
elseif (isset($foo)):
echo "Only 'foo' is set.";
else:
echo "Only 'bar' is set.";
endif;
?>
Example 2:
<?php
$foo = 'foo';
$bar = 'bar';
if (isset($bar)):
if (isset($foo)) {
echo "Both are set.";
}
elseif (isset($foo)):
echo "Only 'foo' is set.";
else:
echo "Only 'bar' is set.";
endif;
?>
Both examples fail with the same error.
Expected result:
----------------
Test Scripts fail. So, this is not a result but a "workaround" for the interpreter to stop failing.
It fixes the parsing error to add an extra semicolon AFTER the last semicolon (before the "elseif:" or "else:") as shown below:
<?php
$foo = 'foo';
$bar = 'bar';
if (isset($bar)):
if (isset($foo)) echo "Both are set.";;
elseif (isset($foo)):
echo "Only 'foo' is set.";
else:
echo "Only 'bar' is set.";
endif;
?>
Or, for the Example 2 (nested traditional "if" with brackets), to add a semicolon AFTER the last closing bracket:
<?php
$foo = 'foo';
$bar = 'bar';
if (isset($bar)):
if (isset($foo)) {
echo "Both are set.";
};
elseif (isset($foo)):
echo "Only 'foo' is set.";
else:
echo "Only 'bar' is set.";
endif;
?>
Ultimately, an empty line with a semicolon in it also do the trick, but none are "PHP standard" and create a huge trouble when debugging. Some people may even get mistaken with the statements and do something foolish like this broken logic (which is validated by the PHP interpreter, of course):
<?php
$foo = 'foo';
$bar = 'bar';
if (isset($bar)):
if (isset($foo)): echo "Both are set.";
elseif (isset($foo)):
echo "Only 'foo' is set.";
else:
echo "Only 'bar' is set.";
endif;
?>
PatchesPull RequestsHistoryAllCommentsChangesGit/SVN commits
|
|||||||||||||||||||||||||||||||||
Copyright © 2001-2025 The PHP GroupAll rights reserved. |
Last updated: Tue Oct 28 13:00:01 2025 UTC |
The assessment of peehaa is correct. PHP is not a whitespace-sensitive language, so the way your code is actually interpreted is as follows: if (isset($bar)): if (isset($foo)) echo "Both are set."; elseif (isset($foo)): echo "Only 'foo' is set."; else: echo "Only 'bar' is set."; endif; This mixes both styles on the same if/elseif/else structure and is, as already noted, not permitted. Please see https://en.wikipedia.org/wiki/Dangling_else for more information about this ambiguity.OMG... Let me draw a picture!!!! [ IF (CONDITION): [ ANYTHING IN HERE SHOULD BE A NESTED BLOCK FOR THE "IF" CONDITION WHEN IT IS TRUE ] ELSEIF (ANOTHER CONDITION): [ ANYTHING IN HERE SHOULD BE A NESTED BLOCK FOR THE "ELSEIF:" CONDITION WHEN IT IS TRUE ] ELSE: [ ANYTHING IN HERE SHOULD BE A NESTED BLOCK FOR THE "ELSE:" CONDITION WHEN IT IS TRUE ] ] Now, based on the nested blocks above, it should NOT fail when you NEST "whatever" statement inside! Each nested block is initiated by the ":" and end when it reaches an "ELSEIF" or an "ELSE" (each one of those having its own nested blocks again after their own ":"), or an "ENDIF" (when the first "IF" ends). It said such code should NOT fail: [ IF (CONDITION): [ ANYTHING IN HERE SHOULD BE A NESTED BLOCK FOR THE "IF" CONDITION WHEN IT IS TRUE IF (ANOTHER CONDITION) [ DO THIS; ] <--- THIS SHOULD BE NESTED INTO THE SAME LINE "IF" ] ELSEIF (ANOTHER CONDITION): [ ANYTHING IN HERE SHOULD BE A NESTED BLOCK FOR THE "ELSEIF:" CONDITION WHEN IT IS TRUE ] ELSE: [ ANYTHING IN HERE SHOULD BE A NESTED BLOCK FOR THE "ELSE:" CONDITION WHEN IT IS TRUE ] ] Or, based on your comment, this following logic should run, but provide a wrong result (and it actually works as expected): $bar = 'bar'; $foo = 'foo'; if (isset($bar)): if (isset($foo)) echo "Both are set."; echo " It actually works."; elseif (isset($foo)): echo "Only 'foo' is set."; else: echo "Only 'bar' is set."; endif; The above code will return: "Both are set. It actually works.", while based on your "thinking" it should return blank. Also, just for thinking purposes, try this (it works): $bar = 'bar'; $foo = 'foo'; if (isset($bar)): echo "It actually works. "; { if (isset($foo)) echo "Both are set."; } elseif (isset($foo)): echo "Only 'foo' is set."; else: echo "Only 'bar' is set."; endif; Does not matter how you look at it, if a nested IF statement (any coding style) precedes an "else:" or an "elseif:" statement, a DOUBLE semicolon is required to make it work (or sub-enclosure it under curly brackets). I can't believe you cannot see it. More (simplified) examples: // FAIL: $bar = 'bar'; if (true): if ($bar == 'bar') echo "Got 'bar'."; else: echo "Didn't get 'bar'."; endif; // WORKS: $bar = 'bar'; if (true): if ($bar == 'bar') echo "Got 'bar'.";; else: echo "Didn't get 'bar'."; endif; // WORKS: $bar = 'bar'; if (true): { if ($bar == 'bar') echo "Got 'bar'."; } else: echo "Didn't get 'bar'."; endif; // FAIL: $bar = 'bar'; if (true): if ($bar == 'bar') { echo "Got 'bar'."; } else: echo "Didn't get 'bar'."; endif; // WORKS: $bar = 'bar'; if (true): if ($bar == 'bar') { echo "Got 'bar'."; }; else: echo "Didn't get 'bar'."; endif;frankly, i consider to propose a RFC to disallow such coding styles at all and would fire anybody writing such code immediately the same for if($× === $y) do_something; without {}