A custom exception is a custom exception class that represents a specific failure within the application domain.
So far, we’ve been using the generic Exception class. However, in real-world applications, throwing a generic Exception for everything (database error, file not found, invalid user) makes it difficult to handle errors intelligently.
Custom exceptions are classes that inherit from Exception and represent domain-specific problems within the application.
Why do it?
Imagine you’re processing a payment. A “Card declined” error (you want to ask for a different card) is not the same as a “Bank server down” error (you want to retry later). If both are just Exception, it’s hard to distinguish them in the catch block.
Basic syntax
To create a custom exception, you simply create a class that extends (inherits from) PHP’s base class.
// Basic definition
class MyCustomError extends Exception {
// Automatically inherits getMessage(), getCode(), etc.
// You can add your own methods if needed.
}Practical example: login system
Let’s simulate a login system where two different things can fail: the email doesn’t exist, or the password is wrong. We’ll create an exception for each case.
1. Define the exceptions
class EmailNotFoundException extends Exception {}
class IncorrectPasswordException extends Exception {}2. Function that throws specific errors
function loginUser($email, $password) {
// Simulated database
$dbEmail = "[email protected]";
$dbPass = "1234";
if ($email !== $dbEmail) {
// Throw the specific email error
throw new EmailNotFoundException("The email $email does not exist in the system.");
}
if ($password !== $dbPass) {
// Throw the specific password error
throw new IncorrectPasswordException("The entered password is not valid.");
}
return "Welcome to the system!";
}3. Selective catch (Multi-Catch)
We can have multiple catch blocks to react differently based on the exception class.
try {
// Attempt to log in (change the values to test different errors)
echo loginUser("[email protected]", "wrong_password");
} catch (EmailNotFoundException $e) {
// Logic A: Maybe redirect to registration
echo "User Error: " . $e->getMessage();
echo "\n -> Would you like to sign up?";
} catch (IncorrectPasswordException $e) {
// Logic B: Maybe show a 'forgot password' button
echo "Security Error: " . $e->getMessage();
echo "\n -> Try again or recover your password.";
} catch (Exception $e) {
// Logic C: A generic catch for any unforeseen non-custom error
echo "Unknown error: " . $e->getMessage();
}Advantages
- Semantic Clarity: The code reads better (
catch (EmailNotFoundException...)is clearer thancatch (Exception...)). - Granular Control: You can make different business decisions for each error without having to do
if ($e->getMessage() == '...'). - Extensibility: Your custom exceptions can have their own methods (for example,
CardDeclinedExceptioncould have a method$e->getIssuingBank()).