Menu
Coddy logo textTech

Command Pattern

Part of the Object Oriented Programming section of Coddy's PHP journey — lesson 75 of 91.

The Command Pattern is a behavioral design pattern that turns a request into a stand-alone object containing all information about the request. This transformation lets you pass requests as method arguments, delay or queue a request's execution, and support undoable operations.

Think of a restaurant.

When you order food, the waiter writes your order on a slip (the command), takes it to the kitchen, and the chef executes it. The waiter doesn't need to know how to cook; they just deliver the command.

This decouples the requester from the executor.

Here's a basic implementation:

<?php
interface Command {
    public function execute(): string;
}
class Light {
    public function on(): string { return "Light is ON"; }
    public function off(): string { return "Light is OFF"; }
}
class LightOnCommand implements Command {
    public function __construct(private Light $light) {}
    
    public function execute(): string {
        return $this->light->on();
    }
}
class LightOffCommand implements Command {
    public function __construct(private Light $light) {}
    
    public function execute(): string {
        return $this->light->off();
    }
}

The invoker triggers commands without knowing what they do:

<?php
class RemoteControl {
    public function press(Command $command): string {
        return $command->execute();
    }
}
$light = new Light();
$remote = new RemoteControl();

echo $remote->press(new LightOnCommand($light)) . "\n";
echo $remote->press(new LightOffCommand($light));

Output:

Light is ON
Light is OFF

The Command Pattern excels when you need to queue operations, implement undo functionality, or log actions. Each command is self-contained, making it easy to add new commands without modifying existing code.

challenge icon

Challenge

Easy

Let's build a text editor command system using the Command Pattern. Text editors often need to support operations like writing text, deleting text, and undoing actions — each operation becomes a self-contained command object that can be executed through a unified interface.

You'll organize your code across four files:

  • Command.php — Define a Command interface with a single method execute(): string. This establishes the contract that all editor commands must follow.
  • TextEditor.php — Create a TextEditor class that represents the receiver — the object that actually performs the work. Your editor should:
    • Store the current text content (start with an empty string)
    • Have a write(string $text): string method that appends text to the content and returns "Written: [text]"
    • Have a clear(): string method that empties the content and returns "Content cleared"
    • Have a getContent(): string method that returns the current content
  • Commands.php — Include the Command and TextEditor files. Create two command classes that implement the Command interface:
    • WriteCommand — Takes a TextEditor and a text string in its constructor. Its execute() method calls the editor's write() method and returns the result.
    • ClearCommand — Takes a TextEditor in its constructor. Its execute() method calls the editor's clear() method and returns the result.
  • main.php — Include the Commands file. You'll receive two inputs: a command type ("write" or "clear") and a text string (used only for write commands).

    Create a TextEditor instance. Based on the command type, create the appropriate command object. Then create an invoker function or simple mechanism that calls execute() on the command and prints the result.

    On a new line, print the editor's current content in this format: Content: [content] (if empty, just print Content: with nothing after the space).

This challenge demonstrates how the Command Pattern encapsulates each operation as an object. The invoker doesn't need to know whether it's executing a write or clear command — it simply calls execute() and lets the command handle the details.

Cheat sheet

The Command Pattern is a behavioral design pattern that encapsulates a request as a stand-alone object containing all information about the request. This allows you to pass requests as method arguments, queue operations, and support undoable actions.

The pattern decouples the requester (invoker) from the executor (receiver), similar to how a waiter delivers orders to a chef without needing to know how to cook.

Basic Structure

Define a Command interface with an execute() method:

interface Command {
    public function execute(): string;
}

Create a receiver class that performs the actual work:

class Light {
    public function on(): string { return "Light is ON"; }
    public function off(): string { return "Light is OFF"; }
}

Implement concrete command classes that encapsulate specific actions:

class LightOnCommand implements Command {
    public function __construct(private Light $light) {}
    
    public function execute(): string {
        return $this->light->on();
    }
}

class LightOffCommand implements Command {
    public function __construct(private Light $light) {}
    
    public function execute(): string {
        return $this->light->off();
    }
}

Invoker

The invoker triggers commands without knowing their implementation details:

class RemoteControl {
    public function press(Command $command): string {
        return $command->execute();
    }
}

$light = new Light();
$remote = new RemoteControl();

echo $remote->press(new LightOnCommand($light)) . "\n";
echo $remote->press(new LightOffCommand($light));

Benefits

The Command Pattern is ideal for queuing operations, implementing undo functionality, or logging actions. Each command is self-contained, making it easy to add new commands without modifying existing code.

Try it yourself

<?php

require_once 'Commands.php';

// Read input
$commandType = trim(fgets(STDIN)); // "write" or "clear"
$text = trim(fgets(STDIN));         // text for write command

// TODO: Create a TextEditor instance

// TODO: Based on the command type, create the appropriate command object
// - If "write", create a WriteCommand with the editor and text
// - If "clear", create a ClearCommand with the editor

// TODO: Create an invoker mechanism that calls execute() on the command
// and prints the result

// TODO: Print the editor's current content in format: "Content: [content]"
// (if empty, just print "Content: " with nothing after the space)

?>
quiz iconTest yourself

This lesson includes a short quiz. Start the lesson to answer it and track your progress.

All lessons in Object Oriented Programming