Eigene Exception-Hierarchie
Teil des Abschnitts Objektorientierte Programmierung der PHP-Journey von Coddy — Lektion 67 von 91.
Während PHPs integrierte Exception-Klassen gängige Szenarien abdecken, benötigen reale Anwendungen oft spezifischere Fehlertypen. Das Erstellen einer benutzerdefinierten Exception-Hierarchie ermöglicht es Ihnen, Exceptions zu definieren, die zu Ihrer Domäne passen, und sie auf verschiedenen Ebenen der Spezifität abzufangen.
Um eine benutzerdefinierte Exception zu erstellen, erweitern Sie einfach die Exception-Klasse oder eine ihrer Unterklassen:
<?php
class PaymentException extends Exception {}
class InsufficientFundsException extends PaymentException {
public function __construct(
private float $required,
private float $available
) {
parent::__construct("Need $required but only $available available");
}
public function getShortfall(): float {
return $this->required - $this->available;
}
}
Beachten Sie, wie InsufficientFundsException PaymentException erweitert und nicht direkt Exception. Dies erzeugt eine Hierarchie, in der Sie alle zahlungsbezogenen Ausnahmen mit einem catch-Block abfangen oder spezifische einzeln behandeln können.
Benutzerdefinierte Exceptions können zusätzliche Eigenschaften und Methoden enthalten, die für den Fehler relevant sind. Hier bietet getShortfall() nützliche Informationen, die eine generische Exception nicht bieten könnte:
<?php
class Wallet {
public function __construct(private float $balance) {}
public function pay(float $amount): void {
if ($amount > $this->balance) {
throw new InsufficientFundsException($amount, $this->balance);
}
$this->balance -= $amount;
}
}
Eine gut entworfene Ausnahmehierarchie macht Ihren Code wartbarer. Beim Abfangen von Ausnahmen können Sie so allgemein oder spezifisch wie nötig vorgehen, und die Ausnahmeobjekte selbst enthalten aussagekräftigen Kontext darüber, was schiefgelaufen ist.
Aufgabe
EinfachLassen Sie uns ein Auftragsverarbeitungssystem mit einer benutzerdefinierten Ausnahmehierarchie aufbauen, die verschiedene Arten von Auftragsfehlern behandelt. Sie werden Ausnahmen erstellen, die einen aussagekräftigen Kontext darüber enthalten, was schiefgelaufen ist, wodurch die Fehlerbehandlung präziser und informativer wird.
Sie werden Ihren Code über vier Dateien organisieren:
OrderException.php— Erstellen Sie eine BasisklasseOrderException, dieExceptionerweitert. Diese dient als Elternklasse für alle auftragsbezogenen Ausnahmen und ermöglicht es Ihnen, bei Bedarf jedes Auftragsproblem mit einem einzigen Catch-Block abzufangen.OutOfStockException.php— Erstellen Sie eine KlasseOutOfStockException, dieOrderExceptionerweitert. Diese Ausnahme sollte einen Produktnamen und die angeforderte Menge in ihrem Konstruktor akzeptieren. Verwenden Sie Constructor Promotion für diese privaten Eigenschaften. Rufen Sie den Eltern-Konstruktor mit einer Nachricht im Format"[productName] is out of stock (requested: [quantity])"auf. Fügen Sie eine MethodegetProductName(): stringhinzu, die den Produktnamen zurückgibt.InvalidQuantityException.php— Erstellen Sie eine KlasseInvalidQuantityException, dieOrderExceptionerweitert. Diese Ausnahme sollte einen Mengenwert in ihrem Konstruktor mittels Constructor Promotion als private Eigenschaft akzeptieren. Rufen Sie den Eltern-Konstruktor mit der Nachricht"Invalid quantity: [quantity]"auf. Fügen Sie eine MethodegetQuantity(): inthinzu, die den Mengenwert zurückgibt.main.php— Binden Sie alle drei Ausnahmedateien ein. Sie erhalten zwei Eingaben: einen Produktnamen und eine Menge (als String, der in einen Integer umgewandelt werden muss).Werfen Sie basierend auf dem Mengenwert die entsprechende Ausnahme:
- Wenn die Menge kleiner als 1 ist, werfen Sie eine
InvalidQuantityException - Wenn die Menge größer als 100 ist, werfen Sie eine
OutOfStockException(um unzureichenden Lagerbestand zu simulieren) - Andernfalls geben Sie
"Order placed: [quantity]x [productName]"aus
Fangen Sie Ausnahmen mithilfe der Hierarchie ab. Fangen Sie zuerst
InvalidQuantityExceptionab und geben Sie"Quantity error: [message] (value: [quantity])"unter Verwendung der Nachricht der Ausnahme und der MethodegetQuantity()aus. Fangen Sie dannOutOfStockExceptionab und geben Sie"Stock error: [message] (product: [productName])"unter Verwendung der Nachricht der Ausnahme und der MethodegetProductName()aus.- Wenn die Menge kleiner als 1 ist, werfen Sie eine
Diese Hierarchie ermöglicht es Ihnen, spezifische Ausnahmen einzeln zu behandeln, während Sie dennoch die Option haben, alle auftragsbezogenen Probleme über die Basisklasse OrderException abzufangen. Die benutzerdefinierten Methoden jeder Ausnahme bieten einen Kontext, den eine generische Ausnahme nicht bieten könnte.
Spickzettel
Erstellen Sie benutzerdefinierte Exceptions, indem Sie die Klasse Exception oder deren Unterklassen erweitern:
<?php
class PaymentException extends Exception {}
class InsufficientFundsException extends PaymentException {
public function __construct(
private float $required,
private float $available
) {
parent::__construct("Need $required but only $available available");
}
public function getShortfall(): float {
return $this->required - $this->available;
}
}
Benutzerdefinierte Exceptions können eine Hierarchie bilden, indem sie andere benutzerdefinierte Exceptions erweitern. Dies ermöglicht das Abfangen von Exceptions auf verschiedenen Spezifitätsebenen – fangen Sie alle zahlungsbezogenen Exceptions mit PaymentException ab oder behandeln Sie spezifische wie InsufficientFundsException einzeln.
Benutzerdefinierte Exceptions können zusätzliche Eigenschaften und Methoden enthalten, um Kontext zum Fehler bereitzustellen:
<?php
class Wallet {
public function __construct(private float $balance) {}
public function pay(float $amount): void {
if ($amount > $this->balance) {
throw new InsufficientFundsException($amount, $this->balance);
}
$this->balance -= $amount;
}
}
Verwenden Sie Constructor Promotion, um Eigenschaften direkt in den Konstruktor-Parametern zu definieren. Rufen Sie parent::__construct() auf, um die Exception-Nachricht festzulegen.
Probier es selbst
<?php
// Alle Exception-Dateien einbinden
require_once 'OrderException.php';
require_once 'OutOfStockException.php';
require_once 'InvalidQuantityException.php';
// Eingabe lesen
$productName = trim(fgets(STDIN));
$quantity = intval(trim(fgets(STDIN)));
// TODO: try-catch verwenden, um die Bestellabwicklung zu handhaben
// Innerhalb des try-Blocks:
// - Wenn quantity < 1, InvalidQuantityException werfen
// - Wenn quantity > 100, OutOfStockException werfen
// - Andernfalls "Order placed: [quantity]x [productName]" ausgeben
//
// Zuerst InvalidQuantityException abfangen:
// - "Quantity error: [message] (value: [quantity])" mit getMessage() und getQuantity() ausgeben
//
// OutOfStockException abfangen:
// - "Stock error: [message] (product: [productName])" mit getMessage() und getProductName() ausgeben
?>Diese Lektion enthält ein kurzes Quiz. Starte die Lektion, um es zu beantworten und deinen Fortschritt zu speichern.
Alle Lektionen in Objektorientierte Programmierung
1Grundlagen der OOP
Externe DateienEinführung in die OOPKlassen vs. ObjekteDas $this-SchlüsselwortMethodenEigenschaftenKonstruktor (__construct)Destruktor (__destruct)Rückblick - Einfacher Taschenrechner4Vererbung
Grundlagen der VererbungDas parent:: SchlüsselwortMethoden überschreibenDas final SchlüsselwortAbstrakte KlassenZusammenfassung – Mitarbeiter-Hierarchie7Kapselung
Public, Protected, PrivateZugriffsmodifikatoren im DetailGetter und SetterInformation HidingConstructor Promotion (8.0)Zusammenfassung – Studentenverwaltungssystem2Namensräume & Autoloading
Einführung in NamensräumeDas use-SchlüsselwortPSR-4 Autoloading-StandardComposer AutoloaderZusammenfassung – Organisiertes Projekt5Interfaces & Verträge
Einführung in InterfacesInterfaces implementierenMehrfache Interface-ImplementierungInterface vs. Abstrakte KlasseType Hinting mit InterfacesZusammenfassung – Formen-Rechner8Magische Methoden
Einführung in magische Methoden__toString & __debugInfo__get, __set, __isset, __unset__call & __callStatic__clone & Objekt-Klonen__serialize & __unserializeZusammenfassung - Eigene Collection11Typsystem & Fehlerbehandlung
TypdeklarationenNullable-TypenUnion- & Intersection-TypenException-KlassenEigene Exception-HierarchieTry, Catch, FinallyZusammenfassung - Formular-Validator14Projekt: Bibliotheksverwaltung
ProjektübersichtBuch- und Benutzerklassen3Klasseneigenschaften
Instanz- vs. statische EigenschaftenKonstanten in KlassenStatische Methoden & EigenschaftenPrivate & geschützte EigenschaftenReadonly-Eigenschaften (PHP 8.1)Zusammenfassung – Bankkonto-Manager6Polymorphismus
Method Overriding erneut betrachtetPolymorphismus über InterfacesType Hinting & Union TypesLate Static BindingZusammenfassung – Payment Processor9Traits
Einführung in TraitsVerwendung mehrerer TraitsKonfliktlösung bei TraitsAbstrakte Methoden in TraitsTraits vs. Vererbung12Entwurfsmuster Teil 1
Einführung in EntwurfsmusterSingleton-MusterFactory-MusterObserver-MusterStrategy-Muster15Abschlussherausforderungen
E-Learning-PlattformBanksystemSpielcharakter-EntwicklungFahrzeugvermietung