Bug #75138 [Nab]: Nested "IF" triggers Exception when it is before "else:" or "elseif:".
| From: | yohgaki@php.net | Date: | Wed, 30 Aug 2017 23:12:11 +0000 |
| Subject: | Bug #75138 [Nab]: 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-210888@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
Updated by: yohgaki@php.net
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:
Searching "dangling else" would help to understand this issue. It's common issue for
languages/programs.
Previous Comments:
------------------------------------------------------------------------
[2017-08-30 22:58:40] spam2 at rhsoft dot net
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 {}
------------------------------------------------------------------------
[2017-08-30 22:38:06] jcmarchi at gmail dot com
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;
------------------------------------------------------------------------
[2017-08-30 22:02:56] spam2 at rhsoft dot net
just take your code, remove any whitespace and look again at it
------------------------------------------------------------------------
[2017-08-30 21:25:00] jcmarchi at gmail dot com
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).
------------------------------------------------------------------------
[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.
------------------------------------------------------------------------
The remainder of the comments for this report are too long. To view
the rest of the comments, please view the bug report online at
https://bugs.php.net/bug.php?id=75138
--
Edit this bug report at https://bugs.php.net/bug.php?id=75138&edit=1