Inheritance

Inheritance: when it helps, when it hurts, and alternatives like composition.

On this page

What Inheritance Is

Inheritance allows a class to extend another class and reuse its behavior. It can be useful, but it also creates tight coupling. In production, prefer composition unless inheritance is clearly the best fit.

Basic Inheritance

<?php
class BaseController {
  protected function json(array $data): void {
    header("Content-Type: application/json; charset=utf-8");
    echo json_encode($data);
  }
}

class ItemController extends BaseController {
  public function index(): void {
    $this->json(["ok" => true]);
  }
}

Overriding Methods

A child class can override methods. Be careful: overrides can introduce subtle behavior changes.

<?php
class Logger {
  public function log(string $msg): void {
    echo $msg;
  }
}

class FileLogger extends Logger {
  public function log(string $msg): void {
    // write to file instead (example)
    file_put_contents("app.log", $msg . PHP_EOL, FILE_APPEND);
  }
}

Composition Often Wins

Composition means “has-a” instead of “is-a”. It reduces coupling and is often easier to test.

<?php
class ReportService {
  private PDO $pdo;

  public function __construct(PDO $pdo) {
    $this->pdo = $pdo;
  }

  public function countItems(): int {
    return (int)$this->pdo->query("SELECT COUNT(*) FROM items")->fetchColumn();
  }
}

Production Tip

Use inheritance for shared infrastructure patterns (base controllers, base exceptions) but avoid deep inheritance trees. Prefer composition for business logic.