Originally published on decentphp.dev — part of the Writing decent PHP course. View this lesson on the original site.
A boolean name should read like a yes/no question
If a variable holds true or false, the name should make that obvious. The reader should be able to look at the name alone and ask: "is this thing X? yes or no."
Names like $status, $user, $account, $flag, or $check do not pass that test.
The fix is almost always a small prefix verb: is, has, can, should, was, did, needs.
Before
The conditions read like statements rather than questions, so the intent is fuzzy.
<?php
function processOrder(array $order, array $customer): bool
{
$status = $order['paid'];
$admin = $customer['role'] === 'admin';
$age = $customer['age'] >= 18;
$check = count($order['items']) > 0;
if ($status && $age && $check) {
return true;
}
if ($admin) {
return true;
}
return false;
}
You can work it out, but every condition makes you pause. if ($status) could mean "if the order has a status", "if the status is set", or "if the order is paid". Only the line above tells you which.
After
Each boolean reads like a yes/no question. The conditions become self-explanatory.
<?php
function processOrder(array $order, array $customer): bool
{
$isPaid = $order['paid'];
$isAdmin = $customer['role'] === 'admin';
$isAdult = $customer['age'] >= 18;
$hasItems = count($order['items']) > 0;
if ($isPaid && $isAdult && $hasItems) {
return true;
}
if ($isAdmin) {
return true;
}
return false;
}
if ($isPaid && $isAdult && $hasItems) reads like a sentence. No mental translation, no scrolling up.
Why this version is better
- the name itself answers "true means what?"
- conditions read top-to-bottom in plain English
- code review can argue the rule (
age >= 18) without first decoding the name - functions returning booleans signal it in their name (
isEligible(),hasAccess(),canPublish())
Boolean prefix cheat sheet
| Prefix | Means | Examples |
|---|---|---|
is |
a state right now | $isPaid, $isActive, $isDeleted |
has |
possession or count > 0 | $hasItems, $hasSubscription, $hasErrors |
can |
capability or permission | $canEdit, $canPublish, $canRefund |
should |
a recommendation or rule | $shouldRetry, $shouldNotify, $shouldSkip |
was |
a past state | $wasCancelled, $wasShipped, $wasPromptedToReview |
did |
a past action | $didConfirmEmail, $didOptOut |
needs |
a required action | $needsReview, $needsApproval |
allows / requires |
policy on something else | $allowsGuestCheckout, $requiresMfa |
Names to avoid
$flag,$check,$status,$ok,$valid— none of these answer the yes/no question- negative names like
$isNotEmpty— read fine on their own, butif (! $isNotEmpty)is double-negative pain. Prefer the positive form ($hasItems) and negate at the call site - ambiguous nouns like
$useror$accountfor booleans — these read as objects, not flags
A small boolean smell test
Read the name out loud as a yes/no question. If it does not naturally answer "yes" or "no", it is not yet a boolean name.
$status— "status what?" → not a boolean name$isPaid— "is paid? yes or no." → boolean name$user— "user what?" → not a boolean name$hasUser— "has a user? yes or no." → boolean name
One verb usually fixes it.
From Writing decent PHP — Naming variables, functions, classes, and files well