BehavioralPHPverifiedVerified

Command Pattern in PHP

Encapsulates a request as an object, allowing you to parameterize clients, queue or log requests, and support undoable operations.

How to Implement the Command Pattern in PHP

1Step 1: Define the command interface

interface Command
{
    public function execute(): void;
    public function undo(): void;
}

2Step 2: Implement concrete commands

class AddTextCommand implements Command
{
    private string $previousContent = '';

    public function __construct(
        private Document $document,
        private readonly string $text,
    ) {}

    public function execute(): void
    {
        $this->previousContent = $this->document->getContent();
        $this->document->append($this->text);
    }

    public function undo(): void
    {
        $this->document->setContent($this->previousContent);
    }
}

class Document
{
    private string $content = '';

    public function append(string $text): void { $this->content .= $text; }
    public function getContent(): string { return $this->content; }
    public function setContent(string $content): void { $this->content = $content; }
}

3Step 3: Implement the invoker with undo history

class Editor
{
    /** @var Command[] */
    private array $history = [];

    public function execute(Command $command): void
    {
        $command->execute();
        $this->history[] = $command;
    }

    public function undo(): void
    {
        $command = array_pop($this->history);
        $command?->undo();
    }
}

// Usage
$doc = new Document();
$editor = new Editor();
$editor->execute(new AddTextCommand($doc, 'Hello '));
$editor->execute(new AddTextCommand($doc, 'World'));
echo $doc->getContent(); // "Hello World"
$editor->undo();
echo $doc->getContent(); // "Hello "

Command Pattern Architecture

hourglass_empty

Rendering diagram...

lightbulb

Command Pattern in the Real World

Think of a restaurant order ticket. A waiter (invoker) takes your order and writes it on a slip (command). The slip is handed to the kitchen (receiver) which executes it. The waiter doesn't cook anything—they just carry and deliver orders. Tickets can be queued, cancelled before cooking, or reviewed in an audit log at day's end.