← Home ← Codex ← DEBT ← Engine
Browse by Category
+ added · updated 7d
← Back to glossary

Memento Pattern

Code Quality PHP 5.0+ Intermediate
debt(d7/e5/b3/t5)
d7 Detectability Operational debt — how invisible misuse is to your safety net

Closest to 'only careful code review or runtime testing' (d7). The detection_hints indicate automated detection is 'no' and the tool listed (phpstan) would not catch pattern-level misuse such as a caretaker inspecting memento internals or missing deep copies — these require human code review. Common mistakes like shallow copies or memory leaks from unbounded history are silent until runtime.

e5 Effort Remediation debt — work required to fix once spotted

Closest to 'touches multiple files / significant refactor in one component' (e5). The quick_fix describes capturing state as an immutable snapshot in a stack, but correcting misuse (e.g. fixing shallow copies across a state-heavy object graph, separating caretaker from originator concerns, or switching to diff-based storage) touches multiple classes and likely ripples through the undo infrastructure. It is not a single-line swap nor a full architectural rework.

b3 Burden Structural debt — long-term weight of choosing wrong

Closest to 'localised tax' (b3). Memento is a localised design choice that applies to specific undo/state-capture subsystems. The applies_to scope covers web and CLI contexts broadly, but the pattern itself only burdens the component implementing undo — the rest of the codebase is largely unaffected unless undo is pervasive.

t5 Trap Cognitive debt — how counter-intuitive correct behaviour is

Closest to 'notable trap (a documented gotcha most devs eventually learn)' (t5). The canonical misconception — that mementos require serialisation — is a documented but non-obvious surprise. Additionally, shallow-copy vs deep-copy confusion and memory exhaustion from unbounded history are well-known gotchas that developers typically discover through experience rather than intuition, making this a notable but not catastrophic trap.

About DEBT scoring →

Also Known As

snapshot pattern undo pattern state snapshot

TL;DR

A behavioural pattern that captures an object's internal state and stores it externally so it can be restored later — enabling undo, snapshots, and versioning without exposing internals.

Explanation

Memento has three roles: Originator (the object whose state is saved), Memento (the snapshot — an opaque object holding saved state), and Caretaker (manages the collection of mementos, initiates save/restore). The key insight: the caretaker never inspects the memento's contents — it just holds them. This preserves encapsulation. PHP applications: undo stacks in editors, game save states, form wizard step history, and domain aggregate snapshots in event sourcing.

Common Misconception

Memento requires serialisation — mementos are opaque objects; they can hold any internal representation as long as the originator can restore from it, including in-memory PHP objects.

Why It Matters

Implementing undo without Memento either exposes internal state (breaking encapsulation) or duplicates state tracking logic — Memento provides a clean, encapsulated solution.

Common Mistakes

  • Caretaker that inspects or modifies memento contents — defeats the encapsulation purpose.
  • Deep copies not made — if state contains objects, shallow copy means memento shares references.
  • Too many mementos for large objects — consider storing diffs rather than full snapshots.
  • Not clearing old mementos — unlimited undo history can exhaust memory.

Code Examples

✗ Vulnerable
// No memento — state lost when form progresses:
class WizardForm {
    public array $step1Data = [];
    public array $step2Data = [];
    // User goes back — step2Data overwritten, step1Data lost
    // No way to restore previous state cleanly
}
✓ Fixed
// Memento pattern:
class WizardForm {
    private array $state = [];

    public function save(): WizardMemento {
        return new WizardMemento($this->state); // Snapshot
    }

    public function restore(WizardMemento $memento): void {
        $this->state = $memento->getState();
    }
}

class WizardMemento {
    public function __construct(private readonly array $state) {}
    public function getState(): array { return $this->state; }
}

// Caretaker:
$history = [];
$history[] = $wizard->save(); // Before step 2
// User goes back:
$wizard->restore(array_pop($history));

Added 16 Mar 2026
Edited 22 Mar 2026
Views 120
Rate this term
No ratings yet
🤖 AI Guestbook educational data only
| |
Last 30 days
0 pings W 0 pings T 2 pings F 0 pings S 1 ping S 0 pings M 0 pings T 0 pings W 1 ping T 0 pings F 0 pings S 1 ping S 2 pings M 0 pings T 0 pings W 1 ping T 0 pings F 0 pings S 1 ping S 0 pings M 0 pings T 0 pings W 0 pings T 0 pings F 1 ping S 0 pings S 0 pings M 0 pings T 0 pings W 1 ping T
No pings yet today
No pings yesterday
Amazonbot 11 Ahrefs 8 ChatGPT 7 Bing 7 Perplexity 6 Google 6 PetalBot 5 SEMrush 5 Majestic 3 Applebot 3 Scrapy 2 Brave Search 2 Meta AI 1 Twitter/X 1 Baidu 1 Unknown AI 1
crawler 64 crawler_json 5
DEV INTEL Tools & Severity
🟢 Low ⚙ Fix effort: Medium
⚡ Quick Fix
Capture object state as an immutable snapshot (Memento) before mutating it — store snapshots in a stack for undo functionality
📦 Applies To
PHP 5.0+ web cli
🔗 Prerequisites
🔍 Detection Hints
Undo functionality implemented by duplicating entire object or storing raw arrays of previous state
Auto-detectable: ✗ No phpstan
🤖 AI Agent
Confidence: Low False Positives: High ✗ Manual fix Fix: Medium Context: Class Tests: Update


✓ schema.org compliant