Bug #75138 [Com]: Nested "IF" triggers Exception when it is before "else:" or "elseif:".

From: Date: Wed, 30 Aug 2017 21:25:02 +0000
Subject: Bug #75138 [Com]: Nested "IF" triggers Exception when it is before "else:" or "elseif:".
References: 1  Groups: php.bugs 
Request: Send a blank email to php-bugs+get-210884@lists.php.net to get a copy of this message
Edit report at https://bugs.php.net/bug.php?id=75138&edit=1 ID: 75138 Comment by: jcmarchi at gmail dot com Reported by: jcmarchi at gmail dot com Summary: Nested "IF" triggers Exception when it is before "else:" or "elseif:". Status: Not a bug Type: Bug Package: *Programming Data Structures Operating System: All PHP Version: Irrelevant Block user comment: N Private report: N New Comment: Sorry, but you are also missing the point... Try this: <?php $bar = 'bar'; $foo = 'foo'; if (isset($bar)): if (isset($foo)) echo "Both are set."; echo "Working now"; elseif (isset($foo)): echo "Only 'foo' is set."; else: echo "Only 'bar' is set."; endif; ?> Now, try this (also works): <?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; ?> Question is: WHY the semicolon after the last nested IF statement is needed ONLY when the last IF is immediately BEFORE an "else:" or "elseif:" statement? Or, better said: why it only fails when the immediate last command BEFORE an "else:" or "elseif:" is an IF statement without an extra (unnecessary, wrongly required) semicolon (;)? Answer: IT IS A BUG in the interpreter/parser! It is not related to "code style", or "indentation", or "coding rules", or "standards", or "language nuances", or "Solar eclipse", etc... It is related to a tested in uncountable scenarios (and real codes) where in all cases it fails exactly the same way (code example is just it: a code example). Previous Comments: ------------------------------------------------------------------------ [2017-08-30 20:59:17] nikic@php.net 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. ------------------------------------------------------------------------ [2017-08-30 20:47:27] jcmarchi at gmail dot com @peehaa. Did you actually READ the bug report????? I don't think so... IT IS A BUG! In the interpreter... The "mixed syntax" is merely an example to display the wrong requirement of the last ";" (and it WORKS). The reported bug fails regardless of the "mixed syntax". Check code examples before saying anything! BTW, it is outrageous the lack of understanding some people has when RTFM! The statement "Mixing syntaxes in the same control block is not supported" refers to the SAME LEVEL BLOCK, not to NESTED BLOCKS (the reason why IT WORKS). -- /me losing faith in the Technology world... :'( ------------------------------------------------------------------------ [2017-08-30 15:57:34] peehaa@php.net From the docs (http://php.net/manual/en/control-structures.alternative-syntax.php): > Mixing syntaxes in the same control block is not supported. ------------------------------------------------------------------------ [2017-08-30 15:31:47] 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; ?> ------------------------------------------------------------------------ -- Edit this bug report at https://bugs.php.net/bug.php?id=75138&edit=1

« previous php.bugs (#210884) next »