« Back
Written by Nuno Maduro on July 28, 2022

Null Object Pattern in PHP

Have you heard about the Null Object Pattern? It’s basically a pattern that allows you to replace null with real objects — and those objects do nothing. And, in this article, I’m going to show how I’ve used it with Symfony’s Console Output feature.

Yesterday I was working with Symfony’s Symfony\Component\Console\Output\ConsoleOutput class - and this is a class that allows me to “write” stuff to the console.

Now, in my code, I had a “MyClass” that contains a public “getter” to receive the current Output implementation.

use Symfony\Component\Console\Output\ConsoleOutput;

class MyClass
{
    public function __construct(private ?ConsoleOutput $output = null)
    {
        // ..
    }

    public function getOutput(): ?ConsoleOutput
    {
        return $this->output;
    }

    // other things my class do... 
}

As you can see, the class above can equally be used without an actually ConsoleOutput implementation, and one issue with this is: that the return type of getOutput may be null. Meaning that consumers of the getOutput method will need to use it in the following way:

$output = $object->getOutput();

if (! is_null($output) {
    $output->write('This works because of the if condition...');
}

Not always, but usually, if a method is returning more than one type, that’s a code smell - specially if is returning a nullable type. Now, there is a simple pattern we can do to improve this. That pattern is called: Null Object Pattern.

For my use case, the Null Object Pattern is about having an object that behaves like ConsoleOutput, but when you call write it should do nothing. In fact, Symfony already ships with a NullOutput for this purpose.

To use the NullOutput from Symfony, let’s first adapt our MyClass implementation, so it can receive any kind of Output. And for that, we can use the Symfony\Component\Console\Output\OutputInterface interface:

use Symfony\Component\Console\Output\OutputInterface;

class MyClass
{
    public function __construct(private OutputInterface $output)
    {
        // ..
    }

    public function getOutput(): OutputInterface
    {
        return $this->output;
    }

    // ... other things my object do
}

Next, when creating an instance of MyClass, if we plan to use a MyClass object without a real ConsoleOutput, we can simply use the NullOutput class instead:

use Symfony\Component\Console\Output\NullOutput;

$output = new NullOutput();
$myObject = new MyClass($output);

Finally, because we’ve used the Null Object Pattern, consumers of MyClass no longer need to verify if an Output instance exists, before using it:


$output = $myObject->getOutput();

-if (! is_null($output) {
-    $output->write('This works because of the if condition...');
-}
+$output->write('This always work...');

I hope you have enjoyed this article. If yes, please consider supporting my work — my mission is to spend more time maintaining the dozens of projects that I've written/collaborated on over the years and continue developing new projects to make PHP development more productive and enjoyable.

github.com/sponsors/nunomaduro