whateverthing.com

PHP Tips: Null Coalesce

PHP 7 and 8 are huge leaps forward for the language. Gone are the days of hacking together an entire web application in a single file (although you can technically still do that, if you're feeling retro). Now there are so many fancy new language features that you might find yourself adrift in the sea of changes.

I'd like to introduce some of these new features one at a time, to give them a chance to catch your attention and capture your imagination.

Today's subject: the Null Coalesce operator, a little ditty from PHP 7.0 that looks like ??.

Why is this a thing??

Way back in Ye PHP Olden Tymes, checking if an array key existed before you used it was something that you had to do very frequently, but was also far more verbose than it had any need to be.

Here are a few examples (don't use them, they're bad on purpose!):

<?php

// apply a default value to a form input
$input = null;
if (!empty($_POST['input'][1])) {
    $input = $_POST['input'][1];
} else {
    $input = 'default';
}

// detect a missing request parameter
if (array_key_exists($_REQUEST['subject'])) {
    echo $_REQUEST['subject'];
} else {
    echo 'Subject not found.';
}

// substitute an empty array when the body array is not provided
$myData = isset($_REQUEST['body']) ? $_REQUEST['body'] : array();
foreach ($myData as $row) {
    echo $row;
}

Without checks like these in place, PHP would write a Notice to your logs.

You did have the option to disable Notices and let your code run free like a kilted Scotsman in a gentle spring breeze, but... that's rarely a good idea.

The Null Coalesce Operator makes it easier to throw some trousers on that wily Scot.

How does it work??

The null coalesce operator (??) is a special comparison operator that reads the value to its left and causes PHP to make a decision:

  • If the value to its left is null or not set, PHP substitutes the value on the right side of the operator.
  • If the value on the left is set and not null, then that value is used.

In some cases, the previous examples of empty(), array_key_exists(), and isset(), can be replaced by ?? for cleaner code.

<?php

// six lines become one
$input = $_POST['input'][1] ?? 'default';

// this one also cleans up nicely
echo $_REQUEST['subject'] ?? 'Subject not found.';

// this one, too
foreach ($_REQUEST['body'] ?? [] as $row) {
    echo $row;
}

Note: All of these examples with $_POST and $_REQUEST are dangerous. They might work OK as syntax demonstrations, but WHOA NELLY is it bad to run code like this in production. Malicious people can inject all kinds of nasty surprises. Look into using a Request library and/or a Validation library from Composer/Packagist as a way to prevent major issues. PHP frameworks like Symfony and Laravel offer built-in tools to keep your users and servers safe.

When does this cause problems??

Null coalesce has one important quirk that can be hard to wrap your head around at first. Because it is a special operator that just dangles there like... something that dangles... PHP can get a bit squirrelly about what constitutes the "left side" and the "right side".

This can result in a bad day.

<?php

$var = null;

echo 'This is my ' . $var ?? 'output' . ' test';
echo "\n";
echo 'This is my ' . ($var ?? 'output') . ' test';
echo "\n";

// Output:
// ---------------------
// This is my
// This is my output test

In the first example, it's easy to expect it to only pay attention to $var, but that's not what happens. Instead, PHP decides that the left-hand side of the check is actually a string containing "This is my " with the contents of $var tacked onto the end. Because this will never be null, the final parts of the string are never concatenated.

Adding the parenthesis is pretty much required in this sort of situation. However, it's not required in all situations. Proceed with caution, and make sure to unit test your code.

There's a bonus in PHP 7.4??

But wait! There's more!

PHP 7.4 introduced the "Null Coalescing Assignment Operator", which takes the Null Coalesce Operator (??) and makes a lovely celtic knot with the Assignment operator (=), resulting in a bouncing baby ??=.

Instead of writing a horror like this:

$myArray['subArray']['key'] = isset($myArray['subArray']['key'])
    ? $myArray['subArray']['key']
    : 'default';

Or like this:

$myArray['subArray']['key'] = $myArray['subArray']['key'] ?? 'default';

Now, you can coalesce it and assign it in one fell swoop:

$myArray['subArray']['key'] ??= 'default';

Beautiful. And a great reason to upgrade to PHP 7.4, if I do say so myself.

What's Next??

This post is the kickoff of a series of short posts about individual PHP features that I think you might like. Next up will be the Arrow Function syntax introduced in PHP 7.4.

Published: April 21, 2020

Categories: coding

Tags: dev, development, coding, php, php-tips