Design Patterns in PHP

Erste Schritte – Design Patterns in PHP: MVC, Singleton und Co.

Design Patterns sind bewährte Lösungs­schablonen für wiederkehrende Architektur­probleme.
In PHP begegnen dir besonders häufig das MVC‑Paradigma für Web‑Apps und klassische GoF‑Patterns wie Singleton, Factory oder Observer.
Dieses Tutorial erklärt Grundidee, Vor- und Nachteile – inklusive kurzer Code‑Skizzen (ausschließlich in <pre>).

1. MVC – Model • View • Controller

  • Model – Daten‑ & Geschäfts­logik (DB‑Zugriffe, Validierung).
  • View  – Präsentations­schicht (HTML/JSON-Ausgabe).
  • Controller – Vermittler, nimmt Request entgegen, ruft Model, wählt View.
/* Router‑Snippet */
$router->add('/user/{id}', 'UserController@show');

/* Controller (app/Controller/UserController.php) */
class UserController {
    public function show(int $id) {
        $user = User::find($id);        // Model
        View::render('user/show', [     // View
            'user' => $user
        ]);
    }
}

Vorteil: Saubere Trennung, erleichtert Tests & Wartung.
Nachteil: Mehr Boilerplate, kann bei sehr kleinen Scripts überdimensioniert wirken.

2. Singleton – genau eine Instanz

Stellt sicher, dass eine Klasse nur ein Objekt besitzt (z. B. Konfig‑Manager, Logger).

class Logger {
    private static ?Logger $instanz = null;
    private function __construct() {}          // privat

    public static function get(): Logger {
        if (self::$instanz === null) {
            self::$instanz = new self();
        }
        return self::$instanz;
    }
    public function info(string $msg): void {
        error_log($msg);
    }
}

/* Nutzung */
Logger::get()->info('Start');

Vorteil: Globale, gemeinsam genutzte Ressource (DB, Config).
Nachteile: Schwer testbar, kann zu versteckter Abhängigkeit und Tight Coupling führen.
In modernen Projekten oft lieber Dependency‑Injection + Container einsetzen.

3. Factory – Objekterzeugung entkoppeln

Die Factory übernimmt komplexe Logik, welches konkrete Objekt zurückgegeben werden soll.

interface Payment {
    public function pay(float $summe): bool;
}

class PayPal implements Payment { /* … */ }
class Stripe  implements Payment { /* … */ }

class PaymentFactory {
    public static function build(string $gateway): Payment {
        return match ($gateway) {
            'paypal' => new PayPal(),
            'stripe' => new Stripe(),
            default  => throw new RuntimeException('Gateway?')
        };
    }
}

$pay = PaymentFactory::build('paypal');
$pay->pay(42.0);

Vorteil: Aufrufende Klassen kennen konkrete Implementierung nicht.
Nachteil: Zusätzliche Factory‑Klassen erhöhen Code‑Menge.

4. Observer / Event – lose gekoppelte Benachrichtigung

Mehrere Objekte können sich bei einem Subject registrieren und werden bei Änderungen informiert.

interface Listener { public function update(string $event): void; }

class EventDispatcher {
    private array $listener = [];
    public function on(string $event, Listener $l): void {
        $this->listener[$event][] = $l;
    }
    public function dispatch(string $event): void {
        foreach ($this->listener[$event] ?? [] as $l) {
            $l->update($event);
        }
    }
}

class MailListener implements Listener {
    public function update(string $event): void {
        // Mail versenden
    }
}

/* Registrierung */
$bus = new EventDispatcher();
$bus->on('user.registered', new MailListener());

/* Auslösen */
$bus->dispatch('user.registered');

Vorteil: Sehr flexibel, Komponenten kennen sich nicht direkt.
Nachteil: Komplexeres Debugging, wer reagiert auf welches Event?

5. Zusammenfassung

  • MVC – Architekturmuster für ganze Apps: Request → Controller → Model → View.
  • Singleton – Eine Instanz, statisch abrufbar (sparsam einsetzen, testbar halten).
  • Factory – Erzeugt passende Objekte, versteckt konkrete Klassen.
  • Observer – Event‑System, lockert Kopplung zwischen Sender / Empfänger.

Fazit

Design Patterns sind keine starren Regeln, sondern Werkzeuge.
Wähle sie, wenn sie dein aktuelles Problem vereinfachen und zukünftige Erweiterungen erleichtern –
nicht, um Checklisten abzuarbeiten.
In PHP‑Projekten kombiniert man häufig MVC als Grundgerüst, Factories zur Objekterstellung,
Events für loses Coupling und – wo sinnvoll – Singletons für gemeinsam genutzte Services.