---
title: "The three nothings of PHP"
url: https://www.exakat.io/the-three-nothings-of-php/
date: 2022-09-13
modified: 2024-02-01
author: "dams"
description: "The three nothings of PHP Mathematicians have the concept of infinity, which represents something that cannot be topped. Strangely enough, infinities come in different sizes : some infinities are larger..."
categories:
  - "Code auditing"
tags:
  - "null"
  - "nullpattern"
  - "type"
  - "void"
image: https://www.exakat.io/wp-content/uploads/2022/09/moon.320.jpg
word_count: 1266
---

# The three nothings of PHP

# The three nothings of PHP

Mathematicians have the concept of infinity, which represents something that cannot be topped. Strangely enough, infinities come in different sizes : some infinities are larger than others. That sounds quite paradoxical, yet somewhat understandable. And yet, there are no less than three nothings in PHP.

On the other hand, PHPians, if we can say that, have three kinds of nothing. The fun part is that they are incompatible one with another. Let's review all them, and see how they behave. They are, in order of appearance : null, void and the uninitialized typed property.

To be clear, we use 'nothing' as a meta-concept, to cover all three of them : the absence of data. There is no keyword 'nothing' in PHP.

## Null

`Null` is probably the first keyword you yelled in your head, when reading the question of the introduction of this post. Of course, `null` is the quintessential value that is nothing.

In fact, when an variable or a property is not defined, it is considered as `null` by PHP.

This is possibly one of the root reason for misunderstanding the `isset()` function. A variable is set when it hold something, some value; and a variable is not set, when it holds nothing, or no value. Since `null`is nothing, a variable does not exist if it holds nothing.

### (unset)

Historically, the old `(unset)` operator used to do that : typecast any value to `null`. The type `null` contains only one value, and, of course, it is `null` : that destroys the requested variable. Unsetting variables used to be equivalent to assign them nothing.

Nowadays, `(unset)` is gone, and unsetting a variable is achieved with the `unset()` function. I love the apparent shift of parenthesis in the syntax : `(unset)` => `unset()`. Quite an upgrade.

## Nothing is still something

The paradoxical nature of `null` is that it is something that represents nothing. Yet, it is possible to add something to `null`and get an integer; it is possible to compare `null` to something else or to itself. It is also possible to assign nothing to a property, and make it unavailable.

In the example below, it is not possible to use `isset()` to distinguish between a property `$p` without a value, property `$n` with a default value of `null` and an undefined property `$x`. In fact, all of them are represented by the `null`.

## Void

`void` is the equivalent of `null`, for types. It represents `nothing`, as a type. It is used for return types of methods.

There is no `void` type available for arguments or properties, since it would mean that such typed variable would always hold nothing, not even `null`. So, `void`-typed variables are simply omitted in the parameters list (same for properties). No need to declare them, so no need to type them either.

### null and void are not compatible

It is noteworthy that `void` is not compatible with `null`. In a `void`method, one has to return without argument, or not return at all. Returning `null` in a `void` method yields an error.

Nothing can be returned, not even null. So `null` is a nothing, and yet, it is something that is not `void`.

### null and void are now both types

Furthermore, the upcoming PHP 8.2 has a dedicated type `Null` : this is useful for method that returns only `null`, but not `void`. Consistently, `void` and `null`are now different types.

Parameters and property may now also use the `null` type. It forces the creation of a variable that consistently contains the `null` value. It is as useless as the `void` parameter, except for one case : to keep the signature of a method unchanged, yet deprecate a parameter by forcing it to `null`. May be to forbid the usage of a property.

### The case of array and void

Finally, there is also the case for array(). Array() looks like a function, though it is actually a language construct. It builds PHP famous arrays.

`array` may contains items, with or without a key. An array may hold a `null`value : in that case, the array contains nothing, and yet it is not empty. An empty array holds something else, which might very well be the elusive `void` value.

Empty arrays are usually processed as a separate case, whenever they are processed. For example, foreach() on an empty array simply ignore all looping and skips the instruction; array_sum() returns a default 0 on an empty array. With custom code, the empty arrays are usually checked with `empty()` or `count() === 0`, and when the array is not empty, then it is processed.

## Uninitialized typed properties

The last case of nothing in PHP is related to typed properties. We have already seen that uninitialized properties are actually set to `null`. It is the traditional process of PHP, anytime undefined values have to be handled.

And yet, typed properties behave differently.

In the code above, the `$p` property is NULL, as expected. On the other hand, `$s` property is ... not `null` : it is a Fatal error. It is still nothing, since it has no default value, but it is also different from `NULL`, as it is not possible to access it until it has been written. Until that moment, the property holds a special nothing that cannot be used.

Indeed, in the case the property needs to be checked before usage, and to avoid a Fatal error, the code must catch the potential error.

## The nothing is eating us!

Bringing together all the notions of 'nothing' leads to intriguing questions. It starts with the paradox that `null` is a value that represents no-value. By itself, it should not exists, and yet, `null` is ubiquitous in PHP code. Many error situations are smoothed by returning `null` and leaving the check to the calling context. There are even dedicated operators, such as `??`and `?->`, which turns those absence of values into default values.

With PHP 8.1, null values are getting less and less needed, as even object-typed properties may get a default value as an object. It entice us to rely less and less on `null` and provide a valid and usable object. This is the [NullPattern](https://designpatternsphp.readthedocs.io/en/latest/Behavioral/NullObject/README.html) design pattern in action.