Benutzerdefinierte Exception-Hierarchie
Teil des Abschnitts Objektorientierte Programmierung der PHP-Journey von Coddy. Lektion 67 von 91.
Während die integrierten Exception-Klassen von PHP häufige Szenarien abdecken, benötigen echte Anwendungen oft spezifischere Fehlertypen. Das Erstellen einer benutzerdefinierten Exception-Hierarchie ermöglicht es dir, Exceptions zu definieren, die zu deiner Domäne passen, und sie auf verschiedenen Ebenen der Spezifität abzufangen.
Um eine benutzerdefinierte Ausnahme zu erstellen, erweiterst du einfach die Klasse Exception 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;
}
}
Beachte, dass InsufficientFundsException PaymentException erweitert und nicht direkt Exception. Dadurch entsteht eine Hierarchie, in der du alle zahlungsbezogenen Ausnahmen mit einem einzigen catch-Block abfangen oder bestimmte Ausnahmen einzeln behandeln kannst.
Benutzerdefinierte exceptions können zusätzliche Eigenschaften und Methoden enthalten, die für den Fehler relevant sind. Hier liefert getShortfall() nützliche Informationen, die eine allgemeine 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 gestaltete Ausnahmehierarchie macht deinen Code wartbarer. Beim Abfangen von Ausnahmen kannst du je nach Bedarf allgemein oder spezifisch vorgehen, und die Ausnahmeobjekte selbst enthalten aussagekräftigen Kontext darüber, was schiefgelaufen ist.
Aufgabe
EinfachErstellen wir ein Auftragsverarbeitungssystem mit einer benutzerdefinierten Ausnahmehierarchie, die verschiedene Arten von Auftragsfehlern behandelt. Du erstellst Ausnahmen, die aussagekräftigen Kontext darüber enthalten, was schiefgelaufen ist, wodurch die Fehlerbehandlung präziser und informativer wird.
Du organisierst deinen Code auf vier Dateien verteilt:
OrderException.php: Erstelle eine BasisklasseOrderException, dieExceptionerweitert. Sie dient als übergeordnete Klasse für alle auftragsbezogenen Ausnahmen und ermöglicht es dir bei Bedarf, jedes Auftragsproblem mit einem einzigen catch-Block abzufangen.OutOfStockException.php: Erstelle eine KlasseOutOfStockException, dieOrderExceptionerweitert. Diese Ausnahme soll in ihrem Konstruktor einen Produktnamen und die angeforderte Menge akzeptieren. Verwende Konstruktor-Promotion für diese privaten Eigenschaften. Rufe den übergeordneten Konstruktor mit einer Nachricht im Format"[productName] is out of stock (requested: [quantity])"auf. Füge eine MethodegetProductName(): stringhinzu, die den Produktnamen zurückgibt.InvalidQuantityException.php: Erstelle eine KlasseInvalidQuantityException, dieOrderExceptionerweitert. Diese Ausnahme soll in ihrem Konstruktor einen Mengenwert akzeptieren und dabei Konstruktor-Promotion für eine private Eigenschaft verwenden. Rufe den übergeordneten Konstruktor mit der Nachricht"Invalid quantity: [quantity]"auf. Füge eine MethodegetQuantity(): inthinzu, die den Mengenwert zurückgibt.main.php: Binde alle drei Ausnahme-Dateien ein. Du erhältst zwei Eingaben: einen Produktnamen und eine Menge (als Zeichenkette, die in eine Ganzzahl umgewandelt werden muss).Wirf abhängig vom Mengenwert die passende Ausnahme:
- Wenn die Menge kleiner als 1 ist, wirf eine
InvalidQuantityException - Wenn die Menge größer als 100 ist, wirf eine
OutOfStockException(um einen unzureichenden Lagerbestand zu simulieren) - Andernfalls gib
"Order placed: [quantity]x [productName]"aus
Fange Ausnahmen mithilfe der Hierarchie ab. Fange zuerst
InvalidQuantityExceptionab und gib"Quantity error: [message] (value: [quantity])"unter Verwendung der Nachricht der Ausnahme und der MethodegetQuantity()aus. Fange anschließendOutOfStockExceptionab und gib"Stock error: [message] (product: [productName])"unter Verwendung der Nachricht der Ausnahme und der MethodegetProductName()aus.- Wenn die Menge kleiner als 1 ist, wirf eine
Mit dieser Hierarchie kannst du bestimmte Ausnahmen einzeln behandeln und hast gleichzeitig die Möglichkeit, alle auftragsbezogenen Probleme über die Basisklasse OrderException abzufangen. Die benutzerdefinierten Methoden jeder Ausnahme liefern Kontext, den eine allgemeine Ausnahme nicht bieten könnte.
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: Verwende try-catch, um die Bestellverarbeitung zu handhaben
// Innerhalb des try-Blocks:
// - Wenn quantity < 1, throw InvalidQuantityException
// - Wenn quantity > 100, throw OutOfStockException
// - Andernfalls, print "Order placed: [quantity]x [productName]"
//
// Catch InvalidQuantityException zuerst:
// - Print "Quantity error: [message] (value: [quantity])" mit getMessage() und getQuantity()
//
// Catch OutOfStockException:
// - Print "Stock error: [message] (product: [productName])" mit getMessage() und getProductName()
?>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 OOPKlassen vs. ObjekteDas Schlüsselwort $thisMethodenEigenschaftenKonstruktor (__construct)Destruktor (__destruct)Rückblick – Einfacher Taschenrechner4Vererbung
Grundlegende VererbungDas Schlüsselwort parent::MethodenüberschreibungDas Schlüsselwort finalAbstrakte KlassenRückblick – Mitarbeiterhierarchie7Kapselung
Öffentlich, geschützt, privatZugriffsmodifikatoren im DetailGetter und SetterInformationsverbergungKonstruktor-Promotion (8.0)Wiederholung – System zur Verwaltung von Schülerdatensätzen2Namespaces & Autoloading
Einführung in NamespacesDas use-SchlüsselwortPSR-4-Autoloading-StandardComposer-AutoloaderRückblick – Organisiertes Projekt5Schnittstellen & Verträge
Einführung in SchnittstellenSchnittstellen implementierenMehrere Schnittstellen implementierenSchnittstelle vs. abstrakte KlasseTyp-Hinweise mit SchnittstellenRückblick – Formrechner8Magische Methoden
Einführung in magische Methoden__toString & __debugInfo__get, __set, __isset, __unset__call & __callStatic__clone & Objektklonen__serialize & __unserializeRückblick – Benutzerdefinierte Sammlung11Typsystem & Fehlerbehandlung
TypdeklarationenNullable-TypenUnion- & Intersection-TypenException-KlassenBenutzerdefinierte Exception-HierarchieTry, Catch, FinallyRückblick – Formularvalidator14Projekt: Bibliotheksverwaltung
ProjektübersichtBuch- und Benutzerklassen3Klassen-Eigenschaften
Instanz- vs. statische EigenschaftenKonstanten in KlassenStatische Methoden & EigenschaftenPrivate & geschützte EigenschaftenSchreibgeschützte Eigenschaften (PHP 8.1)Zusammenfassung – Bankkonto-Manager6Polymorphie
Methodenüberschreibung erneut betrachtetPolymorphie über SchnittstellenTyp-Hinweise & Union-TypenSpätes statisches BindenRückblick – Zahlungsabwickler9Traits
Einführung in TraitsMehrere Traits verwendenAuflösung von Trait-KonfliktenAbstrakte Methoden in TraitsTraits vs. Vererbung12Entwurfsmuster Teil 1
Einführung in EntwurfsmusterSingleton-MusterFactory-MusterObserver-MusterStrategy-Muster15Abschließende Herausforderungen
E-Learning-PlattformBankingsystemEntwicklung einer SpielfigurFahrzeugvermietungÜbe selbstständig: Online-PHP-Compiler