if / elseif / else
<?php
$score = 78;
if ($score >= 90) {
echo "A";
} elseif ($score >= 75) {
echo "B";
} elseif ($score >= 60) {
echo "C";
} else {
echo "F";
}
// Single statement - braces optional but recommended
if ($score >= 60) echo "Pass";
// Multiple conditions with && and ||
if ($age >= 18 && $hasLicense) {
echo "Can drive";
}
Even for one-line ifs, write the braces. It prevents the classic "adding a second line accidentally breaks the condition" bug and matches modern PHP coding style (PSR-12).
Truthy & Falsy Values
Any value can be used as a condition. PHP coerces it to bool:
<?php
// FALSY values
if (false) {} // skip
if (null) {} // skip
if (0) {} // skip
if (0.0) {} // skip
if ("") {} // skip
if ("0") {} // skip <-- surprising
if ([]) {} // skip
// TRUTHY - everything else
if ("0.0") {} // run!
if ("false") {} // run!
if (-1) {} // run
if (" ") {} // run (string with a space)
switch Statement
<?php
$role = "editor";
switch ($role) {
case "admin":
echo "Full access";
break;
case "editor":
case "author": // multiple cases share code
echo "Can edit";
break;
case "viewer":
echo "Read only";
break;
default:
echo "Unknown role";
}
switch (1) matches case "1". This bites when you switch on user input. PHP 8's match uses strict === - prefer it.
match Expression (PHP 8.0+)
The modern replacement for switch - shorter, safer, and returns a value:
<?php
$role = "editor";
$access = match ($role) {
"admin" => "full",
"editor", "author" => "edit", // multiple values per arm
"viewer" => "read",
default => "none",
};
echo $access; // edit
// match can run expressions on the right
$discount = match (true) {
$total >= 1000 => 0.20,
$total >= 500 => 0.10,
$total >= 100 => 0.05,
default => 0,
};
| Feature | switch | match |
|---|---|---|
| Comparison | Loose == | Strict === |
| Returns value | No | Yes |
| Fall-through | Yes (needs break) | No |
| Default behavior on miss | Skip silently | Throw UnhandledMatchError |
| Multiple values per arm | Stacked cases | Comma-separated |
Ternary & Null Coalesce
For tiny if-else expressions, use the ternary or null coalesce instead:
<?php
// Standard ternary
$status = $active ? "online" : "offline";
// Short ternary (Elvis) - falsy fallback
$name = $input ?: "Guest";
// Null coalescing - missing-key fallback
$lang = $_GET["lang"] ?? "en";
// Chained
$value = $primary ?? $secondary ?? $default;
Guard Clauses
Return early on bad input to avoid pyramid-of-doom nesting:
<?php
// BAD - deep nesting
function chargeUser($user, $amount) {
if ($user !== null) {
if ($user->isActive()) {
if ($amount > 0) {
// real work hidden 3 levels deep
return $user->charge($amount);
}
}
}
return false;
}
// GOOD - guard clauses
function chargeUser($user, $amount) {
if ($user === null) return false;
if (!$user->isActive()) return false;
if ($amount <= 0) return false;
return $user->charge($amount);
}
Alternative Syntax for Templates
Inside HTML, replace braces with : and end*:
<?php if ($user->isAdmin()): ?>
<a href="/admin">Admin Panel</a>
<?php elseif ($user->isEditor()): ?>
<a href="/editor">Editor</a>
<?php else: ?>
<a href="/login">Login</a>
<?php endif; ?>