PHP Command Pattern
A short screencast: the Command pattern — turn a request into an object. The remote stores a command and invokes it without knowing what will happen: the light turns on or off.
Overview
A command turns a request into a separate object with an execute method. The client creates a command and hands it to the invoker — the remote. The remote stores the command and, when the button is pressed, simply calls execute, knowing neither the light nor what will actually happen. The command itself holds a reference to the receiver — the light — and decides which of its methods to call. The request thus becomes a standalone object: it can be stored, passed around and swapped.
UML diagram
Code
Command.php
interface Command
{
public function execute(): string;
}
Light.php
class Light
{
public function on(): string
{
return 'Light is on';
}
public function off(): string
{
return 'Light is off';
}
}
LightOnCommand.php
class LightOnCommand implements Command
{
public function __construct(private Light $light) {}
public function execute(): string
{
return $this->light->on();
}
}
LightOffCommand.php
class LightOffCommand implements Command
{
public function __construct(private Light $light) {}
public function execute(): string
{
return $this->light->off();
}
}
RemoteControl.php
class RemoteControl
{
private ?Command $command = null;
public function setCommand(Command $command): void
{
$this->command = $command;
}
public function pressButton(): ?string
{
return $this->command?->execute();
}
}
demo.php
require_once 'Command.php';
require_once 'Light.php';
require_once 'LightOnCommand.php';
require_once 'LightOffCommand.php';
require_once 'RemoteControl.php';
$light = new Light;
$remote = new RemoteControl;
$remote->setCommand(new LightOnCommand($light));
echo $remote->pressButton().PHP_EOL;
$remote->setCommand(new LightOffCommand($light));
echo $remote->pressButton().PHP_EOL;
Example output
Running php demo.php makes the remote invoke two commands in turn, turning the light on and off:
Light is on
Light is off
Advantages
- Turns a request into an object: a command can be stored, passed around and logged.
- The invoker knows neither the receiver nor the operation itself.
- New commands are added without touching the remote or the client.
- Makes queues, undo and redo straightforward to implement.
When to use
- When an object must be parameterised with an action.
- When requests should be queued, logged or undone.
- When the invoker and the receiver must not know about each other.
- When the same operation is triggered from several places.
Usage in Laravel
In Laravel a command is a queued job: a class under app/Jobs/* implements handle(), and dispatch() puts it on a queue from which a worker invokes it without knowing the details. The same idea applies to the Artisan command class (Illuminate\Console\Command) with its handle() method and to the Illuminate\Bus\Dispatcher, which routes a command to its handler.