php 68 lines · 9 steps

Undo/redo with two stacks in PHP

A form editor tracks state history using paired undo and redo stacks so every change can be reversed and replayed.

Explained by highlit
1final class FormEditorHistory
2{
3 private SplStack $undoStack;
4 private SplStack $redoStack;
5 private array $state;
6 private int $limit;
7 
8 public function __construct(array $initialState = [], int $limit = 50)
9 {
10 $this->undoStack = new SplStack();
11 $this->redoStack = new SplStack();
12 $this->state = $initialState;
13 $this->limit = $limit;
14 }
15 
16 public function apply(array $changes): array
17 {
18 $this->undoStack->push($this->state);
19 $this->redoStack = new SplStack();
20 
21 if ($this->undoStack->count() > $this->limit) {
22 $this->undoStack->shift();
23 }
24 
25 $this->state = array_replace($this->state, $changes);
26 
27 return $this->state;
28 }
29 
30 public function undo(): array
31 {
32 if ($this->undoStack->isEmpty()) {
33 return $this->state;
34 }
35 
36 $this->redoStack->push($this->state);
37 $this->state = $this->undoStack->pop();
38 
39 return $this->state;
40 }
41 
42 public function redo(): array
43 {
44 if ($this->redoStack->isEmpty()) {
45 return $this->state;
46 }
47 
48 $this->undoStack->push($this->state);
49 $this->state = $this->redoStack->pop();
50 
51 return $this->state;
52 }
53 
54 public function canUndo(): bool
55 {
56 return !$this->undoStack->isEmpty();
57 }
58 
59 public function canRedo(): bool
60 {
61 return !$this->redoStack->isEmpty();
62 }
63 
64 public function current(): array
65 {
66 return $this->state;
67 }
68}
01 / 01
STEP 01

Walkthrough

Space play step click any line
Three takeaways
  1. 1Two stacks are enough to model reversible history: pop from one and push onto the other to move between past and future.
  2. 2Any fresh edit invalidates the redo future, so clearing the redo stack on apply keeps history consistent.
  3. 3Capping the undo stack bounds memory while still preserving the most recent, most useful history.

Related explainers

Share this explainer

Here's the card — post it anywhere.

Undo/redo with two stacks in PHP — share card
Made with highlit — turn any snippet into a walkthrough like this in about a minute.
Explain your code