Your country

Tools that support it use your country for local currency, number formats, units and paper size. Your choice is saved only in this browser.

Type a name or a two-letter code. Use the up and down arrow keys to move through the countries, Enter to choose one and Escape to close.

PHP (8.5)  Module 2 – Values, variables and types

Booleans, null and which values count as false

The eight values PHP treats as false, how isset(), empty() and is_null() differ, and why ?? keeps a quantity of 0 where ?: replaces it.

Free core, Pro depth: 4 of 10 minutes free
Free: Eight values count as false, and nearly every other value counts as true · isset(), empty() and null coalescing ask different questions. With a pass: 2 in-depth parts and 3 interview answers, about 6 minutes.

What you will learn

  • List the values PHP converts to false, and spot the surprising truthy ones
  • Choose between isset(), empty() and is_null() for a check
  • Use ?? and ??= for missing values, and ?: only where every falsy value should be replaced
  • Read values through a chain that may hold null with the nullsafe operator ?->
  • Convert yes and no text into true, false or null with filter_var()

Before you start

What you’ll learn · Before you start

What you will learn

  • List the values PHP converts to false, and spot the surprising truthy ones
  • Choose between isset(), empty() and is_null() for a check
  • Use ?? and ??= for missing values, and ?: only where every falsy value should be replaced
  • Read values through a chain that may hold null with the nullsafe operator ?->
  • Convert yes and no text into true, false or null with filter_var()

Before you start

On this page

A shop’s order form sends a quantity of 0 to remove an item, and the order is saved with a quantity of 1. The line $qty = $form['qty'] ?: 1; replaced the real 0, because PHP counts '0', like 0 and an empty string, as false.

This lesson shows which values count as false in PHP, then sorts out the checks and operators that look alike, isset(), empty() and is_null(), ?? and ?:, so that a default fills in what is missing and never what is zero.

Eight values count as false, and nearly every other value counts as true

PHP has two booleans, true and false, and the two literals may be written in any case. Booleans come out of comparisons and checks, and PHP also converts any other value to one of them whenever a condition needs it: in an if, in ! and in &&. This program converts fourteen values with (bool):

truthiness_table.php: fourteen values converted to bool PHP · truthiness_table.php
<?php

$values = [false, 0, 0.0, -0.0, '', '0', [], null, '0.0', ' ', '00', 'false', [0], -1];

foreach ($values as $value) {
    $shown = is_array($value) ? json_encode($value) : var_export($value, true);
    printf("%-8s %s\n", $shown, var_export((bool) $value, true));
}

Output

false    false
0        false
0.0      false
-0.0     false
''       false
'0'      false
[]       false
NULL     false
'0.0'    true
' '      true
'00'     true
'false'  true
[0]      true
-1       true

Recorded with PHP 8.5.11 (cli) (NTS) on macOS 26 arm64. To run it yourself: php truthiness_table.php

The first eight lines are the values that count as false: false, the integer 0, the floats 0.0 and -0.0, the empty string, the string '0', the empty array and null. The manual adds only some internal objects, such as a GMP number equal to 0. Everything else is true, and the last six lines are the surprises: '0.0', a single space, '00', the word 'false', an array that holds a 0, and -1. Step through the rule, one type at a time:

Interactive · step by step Which value of each type counts as false Step through the types one at a time. The left column is the type, the right column the only values of it that count as false.
Which value of each type counts as false, step 7 of 7. Showing bool, false itself, int, 0, float, 0.0 and -0.0, string, '' and '0', array, [] only, null, always false, object, never. In focus: never.boolfalse itselfint0-1 and 7 are truefloat0.0 and -0.00.1 and -2.5 are truestring'' and '0''0.0', ' ' and 'false' are truearray[] only[0] is truenullalways falseobjectneverbut some internal objects

The drawing shows the whole scene; its 7 steps are listed below.

Every step as text
  1. bool. A bool needs no conversion. false is false and true is true, whether they are written in small or capital letters.
  2. int. Of all the integers only 0 counts as false. -1 is true, like every other number that is not zero, as the last line of the table showed.
  3. float. 0.0 and -0.0 count as false. Every other float counts as true, however small it is, so 0.1 and -2.5 are both true.
  4. string. Only the empty string and the string '0' count as false. '0.0', a single space, '00' and the word 'false' are all true: PHP looks at the characters, not at what they mean.
  5. array. An array is false only when it has no elements. [0] holds one element, so it is true, although that element is false.
  6. null. null, the value of a variable that has none, is always false. It is the value isset() and ?? look for.
  7. object. Every object counts as true, even one with no properties. The manual names only some internal objects as exceptions, such as a GMP number equal to 0.

Which values count as false depends on the type and the value, never on what a piece of text says: 'false' is a non-empty string, so it is true. The value null: The value of a variable that has no value: one that was never set, or was set to null. It counts as false, turns into empty text, and isset() and ?? treat it like a missing value. is the only value of its own type, the value of a variable that was never set or was set to null, and it is always false.

Checkpoint

Check: Values that count as false

  1. Question 1 of 2 Which of these values counts as false?

    Choose one answer.

    Show the answer: Question 1 of 2

    Answer: '0'

    The falsy values are false, 0, 0.0, -0.0, '', '0', [] and null. Every other value counts as true.

  2. Question 2 of 2 After $debug = 'false';, does if ($debug) run its block?

    Choose one answer.

    Show the answer: Question 2 of 2

    Answer: Yes, because 'false' is a non-empty string other than '0'

    Text such as 'false', 'no' or 'off' is true in a condition. Convert text switches to real booleans where they are read.

isset(), empty() and null coalescing ask different questions

Form data and settings arrive as arrays, in which a key may be missing, may hold null, or may hold an empty string or '0'. This program asks the same four questions about five keys:

form_defaults.php: four checks on five keys PHP · form_defaults.php
<?php

$form = ['coupon' => null, 'note' => '', 'qty' => '0', 'size' => 'M'];

echo "key     isset empty ??    ?:\n";
foreach (['gift', 'coupon', 'note', 'qty', 'size'] as $key) {
    $isset = var_export(isset($form[$key]), true);
    $empty = var_export(empty($form[$key]), true);
    $coalesce = var_export($form[$key] ?? 'x', true);
    $ternary = var_export($form[$key] ?: 'x', true);
    printf("%-7s %-5s %-5s %-5s %s\n", $key, $isset, $empty, $coalesce, $ternary);
}

var_dump(is_null($form['coupon']), array_key_exists('coupon', $form), array_key_exists('gift', $form));

Output

key     isset empty ??    ?:

Warning: Undefined array key "gift" in form_defaults.php on line 10
gift    false true  'x'   'x'
coupon  false true  'x'   'x'
note    true  true  ''    'x'
qty     true  true  '0'   'x'
size    true  false 'M'   'M'
bool(true)
bool(true)
bool(false)

Recorded with PHP 8.5.11 (cli) (NTS) on macOS 26 arm64. To run it yourself: php form_defaults.php

isset() was true only for keys that exist and are not null. empty() was true for the missing key and for every value that counts as false, '0' included, which surprises form handlers. ?? is the null coalescing operator: ??, which returns its left side unless that is null or does not exist, and its right side otherwise. It gives no warning for a missing variable or key, and it keeps 0 and empty text.: it returned its left side unless that was null or missing, so qty kept its '0' and the missing gift got the default 'x', without a warning. ?:, the short ternary, fell back on every value that counts as false, so it replaced '' and '0' too, the bug of the opening, and it warned about the missing key. is_null() was true for the coupon, but only array_key_exists() told a key set to null from a key that is not there.

?: as the default for numbers and text

$qty = $form['qty'] ?: 1; turns a real 0 into 1. Write $qty = $form['qty'] ?? 1;, which replaces only a missing or null value and keeps '0' and ''.

Three more tools build on these rules:

  • ??= assigns a default only when the variable or the key is missing or null.
  • The nullsafe operator ?-> stops at the first null in a chain of properties or method calls and gives null.
  • filter_var() with FILTER_VALIDATE_BOOL turns text such as yes, on and 1 into true, and no, off and 0 into false.

Key idea

Use ?? for a value that may be missing, and ?: only when every value that counts as false should be replaced, which is rarely the case for numbers and text.

Checkpoint

Check: isset(), empty(), ?? and ?:

  1. Question 1 of 2 With $form = ['qty' => '0'];, what is $form['qty'] ?? 1?

    Choose one answer.

    Show the answer: Question 1 of 2

    Answer: '0'

    ?? keeps every value that is set and not null, 0 and '' included. Use it for defaults of numbers and text.

  2. Question 2 of 2 What does empty('0') return?

    Choose one answer.

    Show the answer: Question 2 of 2

    Answer: true

    empty($x) is true when $x is missing or counts as false, which is why it rejects a quantity of '0'.

Defaults that keep 0, and null chains that do not crash Pro: opens with a Pro, Premium or Ultimate pass

?? and ??= fill in defaults without touching 0 or an empty string, and ?-> reads through objects that may be missing. The runs below show both, the precedence trap of ??, and the one case that each of them does not cover.

In this part:

  • Assigning defaults, and the precedence trap of null coalescing
  • The nullsafe operator on a decoded JSON response, line by line

2 runnable examples (PHP) · about 7 minutes

Opening this part with your pass…

This part opens with any MySmartCoPilot pass.

  • Pro pass · 1 week₹79$2.99
  • 30 days₹179$5.99
  • 1 year₹1,699$45

One payment; a pass never renews. The price shown is the total you pay: no fees or charges are added at checkout.

It also opens every other in-depth part in Learn and every Pro tool. Sales are final, except where the law gives you a right to withdraw, for example in the EU and the UK (refund policy).

Booleans from text: filter_var(), (bool) traps and NAN Pro: opens with a Pro, Premium or Ultimate pass

Text from forms, query strings and environment variables is never a boolean until you convert it. This part converts it with filter_var(), reproduces the cast that turns the word false into true, and shows the two floats that are tricky in conditions.

In this part:

  • Reading yes and no from text, input by input
  • The word false that turns a feature on, reproduced
  • NAN and negative zero in conditions, and the 8.5 warning

3 runnable examples (PHP) · about 5 minutes

Opening this part with your pass…

This part opens with any MySmartCoPilot pass.

  • Pro pass · 1 week₹79$2.99
  • 30 days₹179$5.99
  • 1 year₹1,699$45

One payment; a pass never renews. The price shown is the total you pay: no fees or charges are added at checkout.

It also opens every other in-depth part in Learn and every Pro tool. Sales are final, except where the law gives you a right to withdraw, for example in the EU and the UK (refund policy).

Practise: defaults that keep a zero

Fix the order form on your own computer

Start from $form = ['qty' => '0'];, $qty = $form['qty'] ?: 1; and $size = $form['size'] ?: 'M';. Run them, rewrite both lines with ??, and check with var_dump() that $qty is '0' and that the warning is gone.

Then answer the lesson’s questions, which start where you are weakest:

Practice that adapts to you

Practise this lesson

7 questions about 6 ideas of this lesson. Each answer is explained at once, and what you get right is kept in this browser.

  1. Question 1 of 7 How many of these count as false: 0, '0', '', '0.0', [], [0], null, ' '?

    Type a number.

    A hint

    Only '' and '0' are falsy strings, and only [] is a falsy array.

    Show the answer: Question 1 of 7

    Answer: 5 values

    0, '0', '', [] and null are falsy. '0.0' and ' ' are non-empty strings and [0] has an element, so those three are true.

  2. Question 2 of 7 After $items = [0];, does if ($items) run its block?

    Choose one answer.

    Show the answer: Question 2 of 7

    Answer: Yes; an array is true as soon as it has an element, whatever the element is

    Only the empty array is falsy. To test the first element, test $items[0] itself.

  3. Question 3 of 7 A function returns 0 when no rows matched and false when the query failed. A caller writes if (!$result) { logError(); }. What goes wrong?

    Choose one answer.

    Show the answer: Question 3 of 7

    Answer: Zero rows also counts as false, so a search that matched nothing is logged as a failure

    When a function can return two different falsy results, test the one you mean exactly, with ===.

  4. Question 4 of 7 After $coupon = null;, what is isset($coupon)?

    Choose one answer.

    Show the answer: Question 4 of 7

    Answer: false

    isset() treats a null value like a missing one. array_key_exists() tells them apart for array keys.

  5. Question 5 of 7 For $form = ['note' => ''];, what are isset($form['note']) and empty($form['note'])?

    Choose one answer.

    Show the answer: Question 5 of 7

    Answer: true and true

    isset() and empty() are not opposites: an empty string is both set and empty, as the note row showed.

  6. Question 6 of 7 $form has no size key. Which line gives $size the value 'M' without a warning?

    Choose one answer.

    Show the answer: Question 6 of 7

    Answer: $size = $form['size'] ?? 'M';

    ?? is the operator for a value that may be missing: it never warns and keeps 0, '0' and ''. ?: warns about a missing key and replaces every value that counts as false.

  7. Question 7 of 7 A profile shows the display name, or the login name when the display name is missing or empty. Which line does that with no warning?

    Choose one answer.

    Show the answer: Question 7 of 7

    Answer: ($user['display'] ?? '') ?: $user['login']

    ?? handles missing, ?: handles empty. Combined, they cover both, which is the rare case where ?: is right.

Interview questions

  1. Fresher · Warm-up

    What is the difference between isset() and empty() in PHP?

    isset($x) asks whether $x exists and is not null. It is false for a variable that was never set, for a missing array key and for null, and true for everything else, 0, '0' and the empty string included. empty($x) asks whether $x is missing or counts as false: it is true for a missing variable or key and for false, 0, 0.0, '', '0', an empty array and null. Neither warns about a missing variable. The two are not opposites: an empty string is both set and empty. That matters for forms, where every field arrives as text, so empty() rejects a quantity of '0'. Use isset() or ?? to ask whether a value is there, and compare the value itself when 0 or '' are real answers.

  2. Fresher to mid

    Customers who set a cart item's quantity to 0 to remove it see it saved with a quantity of 1. The handler reads the field with $qty = $_POST['qty'] ?: 1. Explain the bug, fix it, and say how you test form handling like this.

    Model answer, Pro. Model answers open with any pass; prices are in the notice on this page. First step and follow-ups

  3. Fresher to mid

    A deployment sets NEW_CHECKOUT=false, yet the new checkout appears for everyone. The code reads if (getenv('NEW_CHECKOUT')) { … }. Explain what happened, and how you read boolean settings safely.

    Model answer, Pro. First step and follow-ups

  4. Mid to senior

    An API client reads $response->data->user->address->city from decoded JSON and fails with "Attempt to read property on null" for some users. Compare ?->, ?? and explicit validation for this code, and say which you choose and why.

    Model answer, Pro. First step and follow-ups

Key takeaways

  • Eight values count as false, false, 0, 0.0, -0.0, '', '0', [] and null; nearly all others count as true, '0.0', 'false' and -1 among them.
  • Booleans come from comparisons and checks, and a condition converts any other value to one of the two booleans.
  • isset() is false for a missing key and for null, empty() is true for both and for every falsy value, and only array_key_exists() tells null from missing.
  • ?? replaces only a missing or null value and ?: every falsy one, so a quantity of 0 needs ??.

Terms in this lesson

null
The value of a variable that has no value: one that was never set, or was set to null. It counts as false, turns into empty text, and isset() and ?? treat it like a missing value.
null coalescing operator
??, which returns its left side unless that is null or does not exist, and its right side otherwise. It gives no warning for a missing variable or key, and it keeps 0 and empty text.

References

Report a problem with this lesson

Quick answers and tool search

Type to search tools or to get a quick answer, for example 18% of 2500. Use the up and down arrow keys to move through the results, Enter to choose, and Escape to close.