Missing {
or }
due to incorrect indentation
Mismatched code braces are common to less well-formatted code such as:
if((!($opt["uniQartz5.8"]!=$this->check58)) or (empty($_POST['poree']))) {if
($true) {echo"halp";} elseif((!$z)or%b){excSmthng(False,5.8)}elseif (False){
If your code looks like this, start afresh! Otherwise it's unfixable to you or anyone else. There's no point in showcasing this on the internet to inquire for help.
You will only be able to fix it, if you can visually follow the nested structure and relation of if/else conditionals and their {
code blocks }
. Use your IDE to see if they're all paired.
if (true) {
if (false) {
…
}
elseif ($whatever) {
if ($something2) {
…
}
else {
…
}
}
else {
…
}
if (false) { // a second `if` tree
…
}
else {
…
}
}
elseif (false) {
…
}
Any double }
}
will not just close a branch, but a previous condition structure. Therefore stick with one coding style; don't mix and match in nested if/else trees.
Apart from consistency here, it turns out helpful to avoid lengthy conditions too. Use temporary variables or functions to avoid unreadable if
-expressions.
IF
cannot be used in expressions
A surprisingly frequent newcomer mistake is trying to use an if
statement in an expression, such as a print statement:
⇓
echo "<a href='" . if ($link == "example.org") { echo …
Which is invalid of course.
You can use a ternary conditional, but beware of readability impacts.
echo "<a href='" . ($link ? "http://yes" : "http://no") . "</a>";
Otherwise break such output constructs up: use multiple if
s and echo
s.
Better yet, use temporary variables, and place your conditionals before:
if ($link) { $href = "yes"; } else { $href = "no"; }
echo "<a href='$href'>Link</a>";
Defining functions or methods for such cases often makes sense too.
Control blocks don't return "results"
Now this is less common, but a few coders even try to treat if
as if it could return a result:
$var = if ($x == $y) { "true" };
Which is structurally identical to using if
within a string concatenation / expression.
- But control structures (if / foreach / while) don't have a "result".
- The literal string "true" would also just be a void statement.
You'll have to use an assignment in the code block:
if ($x == $y) { $var = "true"; }
Alternatively, resort to a ?:
ternary comparison.
If in If
You cannot nest an if
within a condition either:
⇓
if ($x == true and (if $y != false)) { ... }
Which is obviously redundant, because the and
(or or
) already allows chaining comparisons.
Forgotten ;
semicolons
Once more: Each control block needs to be a statement. If the previous code piece isn't terminated by a semicolon, then that's a guaranteed syntax error:
⇓
$var = 1 + 2 + 3
if (true) { … }
Btw, the last line in a {…}
code block needs a semicolon too.
Semicolon too early
Now it's probably wrong to blame a particular coding style, as this pitfall is too easy to overlook:
⇓
if ($x == 5);
{
$y = 7;
}
else ←
{
$x = -1;
}
Which happens more often than you might imagine.
- When you terminate the
if ()
expression with ;
it will execute a void statement. The ;
becomes a an empty {}
of its own!
- The
{…}
block thus is detached from the if
, and would always run.
- So the
else
no longer had a relation to an open if
construct,
which is why this would lead to an Unexpected T_ELSE syntax error.
Which also explains a likewise subtle variation of this syntax error:
if ($x) { x_is_true(); }; else { something_else(); };
Where the ;
after the code block {…}
terminates the whole if
construct, severing the else
branch syntactically.
Not using code blocks
It's syntactically allowed to omit curly braces {
…}
for code blocks in if
/elseif
/else
branches. Which sadly is a syntax style very common to unversed coders. (Under the false assumption this was quicker to type or read).
However that's highly likely to trip up the syntax. Sooner or later additional statements will find their way into the if/else branches:
if (true)
$x = 5;
elseif (false)
$x = 6;
$y = 7; ←
else
$z = 0;
But to actually use code blocks, you do have to write {
…}
them as such!
Even seasoned programmers avoid this braceless syntax, or at least
understand it as an exceptional exception to the rule.
Else / Elseif in wrong order
One thing to remind yourself is the conditional order, of course.
if ($a) { … }
else { … }
elseif ($b) { … }
↑
You can have as many elseif
s as you want, but else
has to go last. That's just how it is.
Class declarations
As mentioned above, you can't have control statements in a class declaration:
class xyz {
if (true) {
function ($var) {}
}
You either forgot a function definition, or closed one }
too early in such cases.
Unexpected T_ELSEIF / T_ELSE
When mixing PHP and HTML, the closing }
for an if/elseif
must be in the same PHP block <?php ?>
as the next elseif/else
. This will generate an error as the closing }
for the if
needs to be part of the elseif
:
<?php if ($x) { ?>
html
<?php } ?>
<?php elseif ($y) { ?>
html
<?php } ?>
The correct form <?php } elseif
:
<?php if ($x) { ?>
html
<?php } elseif ($y) { ?>
html
<?php } ?>
This is more or less a variation of incorrect indentation - presumably often based on wrong coding intentions.
You cannot mash other statements inbetween if
and elseif
/else
structural tokens:
if (true) {
}
echo "in between"; ←
elseif (false) {
}
?> text <?php ←
else {
}
Either can only occur in {…}
code blocks, not in between control structure tokens.
- This wouldn't make sense anyway. It's not like that there was some "undefined" state when PHP jumps between
if
and else
branches.
- You'll have to make up your mind where print statements belong to / or if they need to be repeated in both branches.
Nor can you part an if/else between different control structures:
foreach ($array as $i) {
if ($i) { … }
}
else { … }
There is no syntactic relation between the if
and else
. The foreach
lexical scope ends at }
, so there's no point for the if
structure to continue.
T_ENDIF
If an unexpected T_ENDIF is complained about, you're using the alternative syntax style if:
⋯ elseif:
⋯ else:
⋯ endif;
. Which you should really think twice about.
A common pitfall is confusing the eerily similar :
colon for a ;
semicolon. (Covered in "Semicolon too early")
As indentation is harder to track in template files, the more when using the alternative syntax - it's plausible your endif;
does not match any if:
.
Using } endif;
is a doubled if
-terminator.
While an "unexpected $end" is usually the price for a forgotten closing }
curly brace.
Assignment vs. comparison
So, this is not a syntax error, but worth mentioning in this context:
⇓
if ($x = true) { }
else { do_false(); }
That's not a ==
/===
comparison, but an =
assignment. This is rather subtle, and will easily lead some users to helplessly edit whole condition blocks. Watch out for unintended assignments first - whenver you experience a logic fault / misbeheviour.
T_IF / T_FOREACH / ...
block. Albeit I wanted to compile a more custom summary for IF/ELSE/ELSEIF questions. – mario