if, else and elseif
Decisions are at the heart of every program: show the login form or the dashboard, charge shipping or not, accept the input or reject it. PHP makes decisions with if, else and elseif, and offers an alternative syntax that reads well inside HTML templates.
if
The condition goes in parentheses. If it's true (or truthy — lesson 9), the block runs:
<?php $temperature = 31; if ($temperature > 30) { echo "It's hot today.\n"; echo "Drink plenty of water.\n"; } echo "Done.\n";
It's hot today. Drink plenty of water. Done.
else and elseif
else runs when the condition is false. elseif tests further conditions in order; the first true one wins and the rest are skipped:
<?php foreach ([95, 82, 67, 45] as $score) { if ($score >= 90) { $grade = "A"; } elseif ($score >= 80) { $grade = "B"; } elseif ($score >= 65) { $grade = "C"; } else { $grade = "F"; } echo "$score: $grade\n"; }
95: A 82: B 67: C 45: F
Order matters: 95 also satisfies $score >= 80, so the highest threshold must be checked first. (PHP also accepts else if with a space; elseif is the usual style.)
Combining conditions
<?php $age = 34; $hasTicket = true; $isVip = false; if ($age >= 18 && ($hasTicket || $isVip)) { echo "Welcome in.\n"; } if (!($age >= 13 && $age <= 19)) { echo "Not a teenager.\n"; } $role = "editor"; if (in_array($role, ["admin", "editor"], true)) { echo "Can publish articles.\n"; }
Welcome in. Not a teenager. Can publish articles.
in_array with true (strict mode) is a neat way to test "is it one of these values?".
Guard clauses
Deeply nested ifs are hard to read. Handle the problem cases first and stop early — with return in a function, or exit in a script:
<?php function checkout(array $cart, ?string $user): string { if ($user === null) { return "Please log in first."; } if ($cart === []) { return "Your cart is empty."; } return "Checking out " . count($cart) . " item(s) for $user."; } echo checkout([], null), "\n"; echo checkout([], "sam"), "\n"; echo checkout(["book", "pen"], "sam"), "\n";
Please log in first. Your cart is empty. Checking out 2 item(s) for sam.
Truthiness traps
Because if accepts any value, it's tempting to write if ($value). That treats 0, "", "0" and [] as false, which is often not what you mean:
<?php $quantity = "0"; // e.g. from a form field if ($quantity) { echo "truthy check: has a quantity\n"; } else { echo "truthy check: no quantity (wrong!)\n"; } if ($quantity !== "") { echo "explicit check: quantity entered\n"; }
truthy check: no quantity (wrong!) explicit check: quantity entered
Compare explicitly — === null, === '', === [], > 0 — whenever 0 or "0" could be a legitimate value.
Comparing strings
=== compares strings exactly, case included. For a case-insensitive comparison, use strcasecmp, which returns 0 when the strings match:
<?php $answer = "YES"; var_dump($answer === "yes"); var_dump(strcasecmp($answer, "yes") === 0); var_dump(strtolower($answer) === "yes");
bool(false) bool(true) bool(true)
Alternative syntax for templates
In files that mix PHP and HTML, braces get lost among the tags. PHP's alternative syntax replaces { with a colon and } with endif;:
<?php $stock = (int) ($_GET['stock'] ?? 0); ?> <?php if ($stock > 10): ?> <p class="ok">In stock</p> <?php elseif ($stock > 0): ?> <p class="warn">Only <?= $stock ?> left!</p> <?php else: ?> <p class="none">Sold out</p> <?php endif; ?>
GET /status.php?stock=25 GET /status.php?stock=3 GET /status.php
> GET /status.php?stock=25 <p class="ok">In stock</p> > GET /status.php?stock=3 <p class="warn">Only 3 left!</p> > GET /status.php <p class="none">Sold out</p>
The same style exists for loops: foreach (...): … endforeach;, for/endfor and while/endwhile.
Try it yourself
Calculate a shipping cost: free over 50, 4.99 for orders of 20 or more, 7.99 otherwise; express shipping adds 10.
Shipping: 14.99 Total: 49.99