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, but if (! $isNotEmpty) is double-negative pain. Prefer the positive form ($hasItems) and negate at the call site
  • ambiguous nouns like $user or $account for 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