Dependency Injection in PHP: vollständiger Leitfaden mit Codebeispielen

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

Dependency Injection in PHP: in der Praxis



Dependency Injection (DI) ist eines der Schlüsselprinzipien von SOLID, das es ermöglicht, flexiblen, testbaren und wartbaren Code zu schreiben. In diesem Artikel werden wir anhand realer Beispiele durchgehen, wie man Abhängigkeitsinjektion in PHP umsetzt, ohne abstrakte Theorien. Sie erfahren, wie Sie starre Kopplungen zwischen Klassen vermeiden und Ihren Code änderungsbereit machen.



Was ist Dependency Injection und warum wird sie benötigt?



Stellen Sie sich vor, Sie haben eine Klasse UserController, die mit einer Datenbank arbeitet. Ohne DI erstellen Sie das Verbindungsobjekt wahrscheinlich direkt innerhalb des Controllers:



class UserController {    private $db;    public function __construct() {        $this->db = new MySQLConnection('localhost', 'user', 'pass');    }}


Dieser Ansatz erzeugt eine starre Kopplung (tight coupling). Wenn Sie auf PostgreSQL umsteigen oder ein Mock-Objekt für Tests verwenden möchten, müssen Sie den Controller-Code ändern. Dependency Injection löst dieses Problem: Abhängigkeiten werden von außen übergeben, nicht innerhalb der Klasse erstellt.



Die Hauptvorteile von DI:

  • Reduzierung der Code-Kopplung
  • Vereinfachung des Testens (Abhängigkeiten können leicht ausgetauscht werden)
  • Wiederverwendbarkeit von Klassen
  • Saubere Architektur und Einhaltung des Prinzips der Abhängigkeitsumkehr (DIP)


Methoden der Abhängigkeitsinjektion in PHP



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



1. Injektion über den Konstruktor



Die gebräuchlichste und empfohlene Methode. Abhängigkeiten werden über die Konstruktorparameter übergeben und in den Eigenschaften der Klasse gespeichert.



<?phpinterface DatabaseInterface {    public function query(string $sql): array;}

class MySQLDatabase implements DatabaseInterface { public function query(string $sql): array { // Reale Logik für die Arbeit mit MySQL return ['id' => 1, 'name' => 'John']; }}

class UserRepository { private DatabaseInterface $db; public function __construct(DatabaseInterface $db) { $this->db = $db; } public function getUser(int $id): array { return $this->db->query("SELECT * FROM users WHERE id = $id"); }}

// Verwendung:$db = new MySQLDatabase();$repo = new UserRepository($db);$user = $repo->getUser(1);?>


Beachten Sie: Wir verwenden das Interface DatabaseInterface. Dies ermöglicht es, die Implementierung leicht auszutauschen – zum Beispiel gegen einen Test-Stub.



2. Injektion über Setter



Wird verwendet, wenn die Abhängigkeit zum Zeitpunkt der Objekterstellung nicht zwingend erforderlich ist oder sich während der Laufzeit ändern kann.



<?phpclass MailService {    private ?MailerInterface $mailer = null;        public function setMailer(MailerInterface $mailer): void {        $this->mailer = $mailer;    }        public function send(string $to, string $subject, string $body): void {        if ($this->mailer === null) {            throw new \\RuntimeException('Mailer not configured');        }        $this->mailer->send($to, $subject, $body);    }}

// Verwendung:$mailService = new MailService();$mailService->setMailer(new SmtpMailer());$mailService->send('user@example.com', 'Hello', 'Body');?>


Nachteil dieses Ansatzes: Sie garantieren nicht, dass die Abhängigkeit vor dem Aufruf der Methode send() gesetzt ist. Daher ist für obligatorische Abhängigkeiten der Konstruktor vorzuziehen.



3. Injektion über die Methode



Die Abhängigkeit wird direkt an die Methode übergeben, in der sie benötigt wird. Nützlich für seltene oder kontextbezogene Abhängigkeiten.



<?phpclass ReportGenerator {    public function generate(DataFetcherInterface $fetcher, string $reportType): array {        $data = $fetcher->                

Blogs

Buchempfehlungen