Abhängigkeitsinjektion (Dependency Injection) in PHP für Anfänger

Online Python-Trainer für Anfänger

Lernen Sie Python einfach ohne theoretische Überlastung. Lösen Sie praktische Aufgaben mit automatischer Überprüfung und schreiben Sie Code direkt im Browser.

Kurs starten

Was ist Dependency Injection in PHP und warum wird es benötigt?

\n\n

Stellen Sie sich vor, Sie bauen ein Haus. Anstatt jeden Ziegel selbst zu machen, bestellen Sie sie einfach und verwenden fertige. Dependency Injection (DI) funktioniert in der Programmierung nach dem gleichen Prinzip – Sie erstellen keine Objekte innerhalb einer Klasse, sondern erhalten sie von außen. Das macht Ihren Code flexibel, testbar und verständlich.

\n\n

In PHP, wie in jeder objektorientierten Sprache, sind Klassen oft von anderen Klassen abhängig. Das Problem entsteht, wenn Abhängigkeiten direkt innerhalb der Klasse erstellt werden – das nennt man feste Kopplung (tight coupling). Dependency Injection löst dieses Problem, indem Abhängigkeiten von außen übergeben werden.

\n\n

Das Problem ohne Dependency Injection

\n

Betrachten wir ein typisches Beispiel, bei dem die Klasse UserService selbst ein Datenbankobjekt erstellt:

\n\n
<?php\nclass Database {\n    public function query($sql) {\n        // Abfragelogik\n        return "Ergebnis: " . $sql;\n    }\n}\n\nclass UserService {\n    private $db;\n    \n    public function __construct() {\n        // Feste Kopplung – die Klasse erstellt die Abhängigkeit selbst\n        $this->db = new Database();\n    }\n    \n    public function getUser($id) {\n        return $this->db->query("SELECT * FROM users WHERE id = $id");\n    }\n}\n\n$service = new UserService();\necho $service->getUser(1);\n?>
\n\n

Probleme dieses Ansatzes:

\n
    \n
  • Database kann nicht durch eine andere Implementierung ersetzt werden (z. B. für Tests)
  • \n
  • Schwer zu testen – man kann keinen Platzhalter (Mock) einsetzen
  • \n
  • Der Code wird monolithisch und schwer erweiterbar
  • \n
\n\n

Lösung: Abhängigkeitsinjektion über den Konstruktor

\n

Jetzt schreiben wir dieselbe Klasse neu, indem wir Dependency Injection verwenden:

\n\n
<?php\nclass UserService {\n    private $db;\n    \n    // Die Abhängigkeit wird von außen übergeben\n    public function __construct(Database $db) {\n        $this->db = $db;\n    }\n    \n    public function getUser($id) {\n        return $this->db->query("SELECT * FROM users WHERE id = $id");\n    }\n}\n\n// Die Abhängigkeit separat erstellen\n$database = new Database();\n$service = new UserService($database);\necho $service->getUser(1);\n?>
\n\n

Jetzt weiß UserService nicht, wie Database erstellt wird. Es verwendet einfach das, was ihm übergeben wurde. Das ist Abhängigkeitsinjektion.

\n\n

Arten von Dependency Injection in PHP

\n

Es gibt drei Hauptmethoden zur Abhängigkeitsinjektion. Betrachten wir jede mit Beispielen.

\n\n

1. Injektion über den Konstruktor (Constructor Injection)

\n

Die gebräuchlichste und empfohlene Methode. Abhängigkeiten werden bei der Erstellung des Objekts über den Konstruktor übergeben.

\n\n
<?php\nclass Logger {\n    public function log($message) {\n        echo "[LOG]: " . $message;\n    }\n}\n\nclass OrderProcessor {\n    private $logger;\n    \n    // Abhängigkeit im Konstruktor\n    public function __construct(Logger $logger) {\n        $this->logger = $logger;\n    }\n    \n    public function process($order) {\n        // Auftragsverarbeitung\n        $this->logger->log("Auftrag verarbeitet: " . $order);\n    }\n}\n\n$logger = new Logger();\n$processor = new OrderProcessor($logger);\n$processor->process("Auftrag #123");\n?>
\n\n

Vorteile: Die Abhängigkeit ist immer verfügbar, das Objekt ist immer in einem gültigen Zustand. Nachteile: Bei vielen Abhängigkeiten kann der Konstruktor umfangreich werden.

\n\n

2. Injektion über Setter (Setter Injection)

\n

Wird verwendet, wenn eine Abhängigkeit optional ist oder während der Laufzeit des Objekts ausgetauscht werden muss.

\n\n
<?php\nclass MailService {\n    private $transport;\n    \n    // Setter für die Abhängigkeit\n    public function setTransport($transport) {\n        $this->transport = $transport;\n    }\n    \n    public function send($to, $mess                

Blogs

Buchempfehlungen