Menu
Coddy logo textTech

Dependency Injection

Teil des Abschnitts Objektorientierte Programmierung der PHP-Journey von Coddy. Lektion 57 von 91.

In der vorherigen Lektion hast du gesehen, wie Komposition es einem Car ermöglicht, ein Engine-Objekt zu enthalten. Aber das Erstellen von Abhängigkeiten innerhalb der Klasse bringt ein Problem mit sich – es macht den Code starr und schwer zu testen. Dependency Injection löst dieses Problem, indem Abhängigkeiten von außen übergeben werden, anstatt sie intern zu erstellen.

Vergleiche diese beiden Ansätze:

<?php
// Ohne DI - Abhängigkeit intern erstellt
class Car {
    private Engine $engine;
    
    public function __construct() {
        $this->engine = new Engine(); // Eng gekoppelt
    }
}

// Mit DI - Abhängigkeit wird übergeben
class Car {
    public function __construct(private Engine $engine) {}
}

$engine = new Engine();
$car = new Car($engine); // Von außen injiziert

Der zweite Ansatz ist Dependency Injection. Das Car erstellt seinen eigenen Motor nicht selbst – es erhält einen. Diese einfache Änderung bietet bedeutende Vorteile: Du kannst verschiedene Motortypen übergeben, Implementierungen zum Testen austauschen, und die Klasse wird flexibler.

Für noch größere Flexibilität kannst du Schnittstellen statt konkreter Klassen injizieren:

<?php
interface EngineInterface {
    public function start(): string;
}

class Car {
    public function __construct(private EngineInterface $engine) {}
    
    public function start(): string {
        return $this->engine->start();
    }
}

Jetzt funktioniert Car mit jeder Klasse, die EngineInterface implementiert – einem Benzinmotor, einem Elektromotor oder einem Mock für Tests. Diese Entkopplung ist der Grund, warum Dependency Injection für das Schreiben wartbarer und testbarer PHP-Anwendungen grundlegend ist.

challenge icon

Aufgabe

Einfach

Erstellen wir ein Benachrichtigungssystem, das die Leistungsfähigkeit der Abhängigkeitsinjektion demonstriert. Statt fest zu codieren, wie Nachrichten gesendet werden, erstellst du ein flexibles System, bei dem die Zustellmethode einfach ausgetauscht werden kann.

Du organisierst deinen Code über vier Dateien:

  • MessageSenderInterface.php: Definiere ein Interface namens MessageSenderInterface mit einer einzigen Methode send(string $recipient, string $message): string. Dieses Interface legt den Vertrag fest, den jeder Nachrichtenversender einhalten muss.
  • EmailSender.php: Erstelle eine Klasse EmailSender, die MessageSenderInterface implementiert. Binde die Interface-Datei ein. Die Methode send() soll "Email to [recipient]: [message]" zurückgeben.
  • NotificationService.php: Erstelle eine Klasse NotificationService, die ihre Abhängigkeit über den Konstruktor erhält. Binde die Interface-Datei ein. Die Klasse soll:
    • In ihrem Konstruktor mithilfe der Konstruktor-Promotion ein MessageSenderInterface akzeptieren
    • Eine Methode notify(string $recipient, string $message) besitzen, die die Aufgabe an den injizierten Sender delegiert und dessen Ergebnis zurückgibt
    Beachte, dass NotificationService vom Interface und nicht von einer konkreten Klasse abhängt. Das bedeutet, dass du jeden Sender injizieren könntest, der das Interface implementiert, ohne den Service zu ändern.
  • main.php: Binde die Dateien für EmailSender und NotificationService ein. Du erhältst zwei Eingaben: einen Empfänger und eine Nachricht. Erstelle ein EmailSender, injiziere es in einen NotificationService, rufe anschließend notify() auf und gib das Ergebnis aus.

Dieses Muster hält deinen NotificationService flexibel. Er funktioniert mit jedem Sender, den du injizierst, unabhängig davon, ob es sich um E-Mail, SMS oder etwas handelt, das du noch nicht erstellt hast. Der Service erstellt seine Abhängigkeiten nicht selbst, sondern erhält sie von außen.

Probier es selbst

<?php
require_once 'EmailSender.php';
require_once 'NotificationService.php';

// Eingabe lesen
$recipient = trim(fgets(STDIN));
$message = trim(fgets(STDIN));

// TODO: Erstelle eine EmailSender-Instanz
// TODO: Injiziere sie in einen NotificationService
// TODO: Rufe notify() auf und gib das Ergebnis aus

?>
quiz iconTeste dich selbst

Diese Lektion enthält ein kurzes Quiz. Starte die Lektion, um es zu beantworten und deinen Fortschritt zu speichern.

Alle Lektionen in Objektorientierte Programmierung

Übe selbstständig: Online-PHP-Compiler