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 OFFThe 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
EasyLet'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 aCommandinterface with a single methodexecute(): string. This establishes the contract that all editor commands must follow.TextEditor.php— Create aTextEditorclass 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): stringmethod that appends text to the content and returns"Written: [text]" - Have a
clear(): stringmethod that empties the content and returns"Content cleared" - Have a
getContent(): stringmethod that returns the current content
Commands.php— Include the Command and TextEditor files. Create two command classes that implement theCommandinterface:WriteCommand— Takes aTextEditorand a text string in its constructor. Itsexecute()method calls the editor'swrite()method and returns the result.ClearCommand— Takes aTextEditorin its constructor. Itsexecute()method calls the editor'sclear()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
TextEditorinstance. Based on the command type, create the appropriate command object. Then create an invoker function or simple mechanism that callsexecute()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 printContent: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)
?>This lesson includes a short quiz. Start the lesson to answer it and track your progress.
All lessons in Object Oriented Programming
1Fundamentals of OOP
External FilesIntroduction to OOPClasses vs ObjectsThe $this KeywordMethodsPropertiesConstructor (__construct)Destructor (__destruct)Recap - Simple Calculator4Inheritance
Basic InheritanceThe parent:: KeywordMethod OverridingThe final KeywordAbstract ClassesRecap - Employee Hierarchy7Encapsulation
Public, Protected, PrivateAccess Modifiers in DepthGetters and SettersInformation HidingConstructor Promotion (8.0)Recap - Student Records System10Advanced OOP Concepts
Composition vs InheritanceDependency InjectionAnonymous ClassesEnums (PHP 8.1)Fibers (PHP 8.1)Object Cloning Deep DiveGenerators & Iterators13Design Patterns Part 2
Command PatternAdapter PatternDecorator PatternTemplate Method PatternState PatternComposite PatternRepository Pattern2Namespaces & Autoloading
Introduction to NamespacesThe use KeywordPSR-4 Autoloading StandardComposer AutoloaderRecap - Organized Project5Interfaces & Contracts
Introduction to InterfacesImplementing InterfacesMultiple Interface ImplementInterface vs Abstract ClassType Hinting with InterfacesRecap - Shape Calculator8Magic Methods
Magic Methods Introduction__toString & __debugInfo__get, __set, __isset, __unset__call & __callStatic__clone & Object Cloning__serialize & __unserializeRecap - Custom Collection11Type System & Error Handling
Type DeclarationsNullable TypesUnion & Intersection TypesException ClassesCustom Exception HierarchyTry, Catch, FinallyRecap - Form Validator14Project: Library Management
Project OverviewBook and User Classes3Class Properties
Instance vs Static PropertiesConstants in ClassesStatic Methods & PropertiesPrivate & Protected PropertiesReadonly Properties (PHP 8.1)Recap - Bank Account Manager6Polymorphism
Method Overriding RevisitedPolymorphism via InterfacesType Hinting & Union TypesLate Static BindingRecap - Payment Processor9Traits
Introduction to TraitsUsing Multiple TraitsTrait Conflict ResolutionAbstract Methods in TraitsTraits vs Inheritance12Design Patterns Part 1
Intro to Design PatternsSingleton PatternFactory PatternObserver PatternStrategy Pattern