Ternary Operator
The ternary operator is PHP's compact way of writing a simple if / else as a single expression instead of a multi-line statement. It takes three operands — a condition, a value for when the condition is true, and a value for when it is false — which is why it is called "ternary" (three parts). Once you get comfortable with it, the ternary operator becomes a natural fit for short assignments, default values, and inline decisions inside echo statements or function calls. Used carelessly, though, it can also turn readable code into a puzzle, so this page covers both the syntax and the judgment calls around it.
The basic form
The full syntax is condition ? valueIfTrue : valueIfFalse. PHP evaluates condition, converts it to a boolean if it is not one already, and then evaluates and returns exactly one of the two remaining operands — never both.
A simple ternary assignment
<?php $age = 20; $status = $age >= 18 ? "adult" : "minor"; echo $status;
adult
This is functionally identical to the longer if / else version below — the ternary is just an expression form, so it can appear anywhere a value is expected, including directly inside an echo.
The equivalent if / else
<?php
$age = 20;
if ($age >= 18) {
$status = "adult";
} else {
$status = "minor";
}
echo $status;Using it inline
Because the ternary operator produces a value rather than a statement, it is often used directly inside string interpolation, function arguments, or echo calls, without needing an intermediate variable.
Inline usage
<?php
$cartCount = 3;
echo "You have {$cartCount} " . ($cartCount === 1 ? "item" : "items") . " in your cart.";You have 3 items in your cart.
The shorthand form (the "Elvis operator")
PHP also supports a two-part shorthand: condition ?: valueIfFalse. When the middle operand is left out like this, PHP evaluates condition once, and if it is truthy, returns condition itself rather than re-evaluating it or returning true. If condition is falsy, it returns valueIfFalse. This shape resembles a sideways smiley face, which is why developers nicknamed it the "Elvis operator."
Shorthand ternary in action
<?php $nickname = ""; $username = "j_doe"; $displayName = $nickname ?: $username; echo $displayName;
j_doe
The shorthand form is especially handy for picking the first "truthy" value out of two candidates, such as falling back to a default when a form field was submitted empty. Remember that this checks general truthiness, not just emptiness or nullness — a value of 0, 0.0, "0", false, null, or an empty array or string will all be treated as falsy and trigger the fallback.
Truthiness, not just null, decides the outcome
<?php $discount = 0; $appliedDiscount = $discount ?: 10; echo $appliedDiscount;
10
Here 0 is a perfectly valid, intentional discount value, but the Elvis operator cannot tell "zero on purpose" apart from "nothing was set," so it silently replaces it with 10. This is one of the most common surprises with the shorthand ternary.
Nested ternaries hurt readability
Hard to read: nested ternaries
<?php $score = 72; $grade = $score >= 90 ? "A" : ($score >= 75 ? "B" : ($score >= 60 ? "C" : "F")); echo $grade;
C
The line above works, but a reader has to mentally unwind three levels of parentheses to figure out which branch produced "C". Rewriting the same logic with if / elseif (or, when the branches are simple equality checks, a match expression) reads top to bottom without any nesting to untangle.
Clearer: if / elseif
<?php
$score = 72;
if ($score >= 90) {
$grade = "A";
} elseif ($score >= 75) {
$grade = "B";
} elseif ($score >= 60) {
$grade = "C";
} else {
$grade = "F";
}
echo $grade;C
Ternary vs. the null coalescing operator
PHP 7 introduced ??, the null coalescing operator, specifically to fix the "is this set and not null" pattern that the ternary operator handled clumsily. $value ?? $default checks whether $value is isset() — meaning it exists and is not null — and returns $default only in that case. Unlike the Elvis operator, ?? does not care about general truthiness: 0, false, "", and [] are all left alone because they are set and non-null.
?? only cares about isset / null
<?php $discount = 0; $appliedDiscount = $discount ?? 10; echo $appliedDiscount; echo "\n"; $page = $_GET['page'] ?? 1; echo $page;
0 1
Notice how $discount survives untouched this time, because 0 is set and not null — this is the exact case where the earlier Elvis example gave the wrong answer. ?? also has an added convenience: it will not raise a warning if the left-hand side is an undefined variable or array key, which makes it the standard tool for reading optional array entries like $_GET or $_POST.
Use the full ternary (
cond ? a : b) when the true and false branches are genuinely different expressions, not just "value or fallback."Use the shorthand Elvis operator (
cond ?: b) when you want to keep a value as-is if it is truthy, and any falsy value (including0or"") should trigger the fallback.Use the null coalescing operator (
cond ?? b) when you specifically want to fall back only on an unset ornullvalue, and treat0,false, and""as legitimate data.For three or more branches based on distinct conditions, reach for
if / elseifor amatchexpression instead of nesting ternaries.
Chaining null coalescing
?? can be chained to check several candidates in order, returning the first one that is set and non-null.
Chained null coalescing
<?php $config = []; $timeout = $config['timeout'] ?? $_ENV['APP_TIMEOUT'] ?? 30; echo $timeout;
30