Table of contents
Open Table of contents
Overview
PHP has evolved from a templating language into a full-featured OOP language with a rich standard library. This reference covers the core concepts you’ll use across the kata exercises.
Object-Oriented Programming
Classes and Inheritance
abstract class Animal {
public function __construct(
protected string $name,
) {}
abstract public function speak(): string;
public function getName(): string {
return $this->name;
}
}
class Dog extends Animal {
public function speak(): string {
return "{$this->name} says: Woof!";
}
}
Interfaces
Interfaces define contracts. A class can implement multiple interfaces:
interface Comparable {
public function compareTo(mixed $other): int;
}
interface Stringable {
public function __toString(): string;
}
class Temperature implements Comparable, Stringable {
public function __construct(private float $degrees) {}
public function compareTo(mixed $other): int {
return $this->degrees <=> $other->degrees;
}
public function __toString(): string {
return "{$this->degrees}°";
}
}
Abstract Classes vs Interfaces
| Feature | Abstract Class | Interface |
|---|---|---|
| Methods | Can have implementations | Only signatures (+ default since PHP 8.0) |
| Properties | Yes | No (until property hooks) |
| Constructor | Yes | No |
| Multiple | Single inheritance | Multiple implementation |
Traits
Horizontal code reuse without inheritance:
trait Timestampable {
private ?DateTimeImmutable $createdAt = null;
private ?DateTimeImmutable $updatedAt = null;
public function setCreatedAt(): void {
$this->createdAt = new DateTimeImmutable();
}
public function getCreatedAt(): ?DateTimeImmutable {
return $this->createdAt;
}
}
class BlogPost {
use Timestampable;
public function __construct(public string $title) {
$this->setCreatedAt();
}
}
Conflict Resolution
class MyClass {
use TraitA, TraitB {
TraitA::method insteadof TraitB;
TraitB::method as methodFromB;
}
}
Closures and Callables
Closures
$multiplier = function (int $factor): Closure {
return fn(int $n): int => $n * $factor;
};
$double = $multiplier(2);
echo $double(5); // 10
Arrow Functions
Short closures with implicit $this and variable capture:
$numbers = [1, 2, 3, 4, 5];
$squared = array_map(fn($n) => $n ** 2, $numbers);
First-Class Callables (PHP 8.1+)
$lengths = array_map(strlen(...), ['hello', 'world']);
Generators
Memory-efficient iteration for large datasets:
function fibonacci(): Generator {
[$a, $b] = [0, 1];
while (true) {
yield $a;
[$a, $b] = [$b, $a + $b];
}
}
$fib = fibonacci();
for ($i = 0; $i < 10; $i++) {
echo $fib->current() . ' ';
$fib->next();
}
// 0 1 1 2 3 5 8 13 21 34
Delegated Generators
function inner(): Generator {
yield 1;
yield 2;
}
function outer(): Generator {
yield 0;
yield from inner();
yield 3;
}
// 0, 1, 2, 3
SPL Data Structures
PHP’s Standard PHP Library provides built-in data structures:
SplStack and SplQueue
$stack = new SplStack();
$stack->push('a');
$stack->push('b');
echo $stack->pop(); // 'b' (LIFO)
$queue = new SplQueue();
$queue->enqueue('a');
$queue->enqueue('b');
echo $queue->dequeue(); // 'a' (FIFO)
SplPriorityQueue
$pq = new SplPriorityQueue();
$pq->insert('low', 1);
$pq->insert('high', 10);
$pq->insert('medium', 5);
echo $pq->extract(); // 'high'
echo $pq->extract(); // 'medium'
SplFixedArray
Fixed-size array with better memory usage:
$arr = new SplFixedArray(5);
$arr[0] = 'hello';
// $arr[10] = 'error'; // RuntimeException
SplDoublyLinkedList
$list = new SplDoublyLinkedList();
$list->push('a');
$list->push('b');
$list->unshift('z'); // prepend
foreach ($list as $item) {
echo $item; // z, a, b
}
SplHeap
class MinHeap extends SplHeap {
protected function compare(mixed $a, mixed $b): int {
return $b <=> $a; // reverse for min-heap
}
}
$heap = new MinHeap();
$heap->insert(5);
$heap->insert(1);
$heap->insert(3);
echo $heap->extract(); // 1
Arrays as Hash Maps
PHP arrays are ordered hash maps — one of the most versatile built-in data structures in any language:
$map = [];
$map['key1'] = 'value1';
$map['key2'] = 'value2';
// Check existence
isset($map['key1']); // true
// Iterate with keys
foreach ($map as $key => $value) {
echo "$key: $value\n";
}
// Array functions as map operations
$keys = array_keys($map);
$values = array_values($map);
$filtered = array_filter($map, fn($v) => strlen($v) > 5);
Error Handling
Exceptions
class InsufficientFundsException extends RuntimeException {
public function __construct(
public readonly float $balance,
public readonly float $amount,
) {
parent::__construct(
"Cannot withdraw {$amount}: balance is {$balance}"
);
}
}
try {
withdraw(100.0);
} catch (InsufficientFundsException $e) {
echo "Balance: {$e->balance}";
} catch (RuntimeException $e) {
echo $e->getMessage();
} finally {
closeConnection();
}
Exception Hierarchy
Throwable
├── Error (internal engine errors)
│ ├── TypeError
│ ├── ValueError
│ └── ...
└── Exception
├── RuntimeException
├── LogicException
│ ├── InvalidArgumentException
│ └── OutOfRangeException
└── ...
Magic Methods
Key magic methods used in data structure implementations:
class Collection implements Countable, ArrayAccess, Iterator {
private array $items = [];
private int $position = 0;
public function __construct(array $items = []) {
$this->items = array_values($items);
}
// Countable
public function count(): int {
return count($this->items);
}
// ArrayAccess
public function offsetExists(mixed $offset): bool {
return isset($this->items[$offset]);
}
public function offsetGet(mixed $offset): mixed {
return $this->items[$offset];
}
public function offsetSet(mixed $offset, mixed $value): void {
if ($offset === null) {
$this->items[] = $value;
} else {
$this->items[$offset] = $value;
}
}
public function offsetUnset(mixed $offset): void {
unset($this->items[$offset]);
$this->items = array_values($this->items);
}
// Iterator
public function current(): mixed { return $this->items[$this->position]; }
public function key(): int { return $this->position; }
public function next(): void { $this->position++; }
public function rewind(): void { $this->position = 0; }
public function valid(): bool { return isset($this->items[$this->position]); }
}
Key Takeaways
- Interfaces over inheritance — prefer composition and contracts
- SPL data structures — use them instead of reinventing wheels in production
- Generators — essential for memory-efficient iteration
- Arrays are hash maps — PHP’s most powerful built-in data structure
- Named arguments + enums + match — modern PHP is expressive and type-safe
Related Katas
- Kata: Stack and Queue — SplStack, SplQueue
- Kata: Linked List — SplDoublyLinkedList comparison
- Kata: Hash Map — PHP arrays as native hash maps
- Kata: Observer Pattern — SplObserver interface
- Kata: Dijkstra’s Shortest Path — SplPriorityQueue