Is there a BUG in PHP "IF block" parsing method or what?

185 views Asked by At

Consider the following hypothetical PHP example:

$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;

Disconsider the dumb logic and focus on the elseif line. If you try it yourself you will get a PHP EXCEPTION error saying "syntax error, unexpected ':' "

Now, you may think the fix is to have the sub-if enclosed in between { } instead of being a single line statement, like this:

$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;

Wrong! The error remains. Exactly the same EXCEPTION as before...

So, what is wrong with those examples?

1

There are 1 answers

6
Julio Marchi On

Well, here is what I found: if you put a semicolon (;) AFTER the curly bracket (}) which resides immediately before the elseif statement, then the error is gone! Try it:

$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;

Weird enough, if you go back to the first example and DOUBLE the semicolon immediately before the elseif statement, it will also work:

$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;

But, it doesn't end there. You can also do this:

$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;

However, in this last example, the logic gets totally scrambled! The elseif will now belong to the sub-if instead of the first if, and the rest of the logic will all behave as a "one single statement" in response to the first if only. Very confusing and error prone (be careful).

The differences are very subtle and can deceive the eyes (especially while debugging). For this reason, I strongly suggest the first example from this answer: when using IF-ELSEIF blocks (AKA "Alternative Syntax"), if another IF is required inside it, enclose it in between {} and don't forget to add a semicolon after the last }. Example:

if (isset($bar)):
   if (isset($foo)) {
     echo "Both are set.";
   };
elseif (...):

Maybe the truth is that someone screwed up in the language parsing process for those PHP Block Alternative Statements or failed to document this very important detail!