In our previous post, we saw how to handle Exception in PHP where we found that there are so many inbuilt Exceptions available, and based on the importance we used them in the different parts of the code. In this tutorial, we will see how we can create our own custom Exception class OR User defined Exception class.
But before moving ahead, we must have noticed that all these exceptions extend to the Exception class which is considered as the parent class, and based on that other child Exception classes are created and are used based on their importance.
Let’s see the built-in class Exception class (Reference php.net site) first and various properties and methods defined in it and then we’ll create our custom class.
<?php class Exception extends Throwable { protected $message = 'Unknown exception'; // exception message private $string; // __toString cache protected $code = 0; // user defined exception code protected $file; // source filename of exception protected $line; // source line of exception private $trace; // backtrace private $previous; // previous exception if nested exception public function __construct($message = null, $code = 0, Throwable $previous = null); final private function __clone(); // Inhibits cloning of exceptions. final public function getMessage(); // message of exception final public function getCode(); // code of exception final public function getFile(); // source filename final public function getLine(); // source line final public function getTrace(); // an array of the backtrace() final public function getPrevious(); // previous exception final public function getTraceAsString(); // formatted string of trace // Overrideable public function __toString(); // formatted string for display } ?>
As we can see, all the properties defined in the Exception class are either having protected or private access modifiers. This means that $message, $code, $file & $line properties are available to exception & it’s child classes.
On the other hand, private members $string, $trace & $previous variables can be accessed & modified by Exception class only and not by any other classes.
All the methods defined are final. This indicates that no method is allowed to override in the child class. But we can create our own custom method in the child class.
Now, let’s see how we can create our own custom exception class-
There is only one basic syntax to create it-
class CustomException extends Exception {}
Let’s start creating our custom Exception class. First, we’ll create a custom exception class and then will see different components inside it.
create our first own custom Exception class
<?php class CustomException extends Exception { public function __construct($message, $code = 0, Exception $previous = null) { parent::__construct($message, $code, $previous); } public function customMessage() { echo "Custom Message will go here\n"; } }
Here, we extended our CustomException class to Exception class and defined constructor which eventually calls parent constructor. As mentioned above we can also define our method inside this class like customMessage() here.
Let’s create a complete working example and then we’ll see it line by line.
<?php class FileNotReadableException extends Exception { private $fileWithError = ''; public function __construct(string $fileName) { $this->fileWithError = $fileName; parent::__construct("The provided file could not be read."); } public function customMessage() { echo "File with Error While Reading is- {$this->fileWithError} \n"; } } class HandleFileOperation { public function checkFileIsReadable($file) { if (!is_readable($file)) { throw new FileNotReadableException($file); } else { // process file } } } $objCustomException = new HandleFileOperation(); try { $objCustomException->checkFileIsReadable("processFile.php"); } catch (FileNotReadableException $e) { echo $e->customMessage(); }
As we can see, checkFileIsReadable() function of HandleFileOperation class throws an exception when the file provided to it is not readable. Inside FileNotReadableException class we have defined our custom function named customMessage(). We can call this function to show a custom message on the screen rather than the predefined one in the parent class Exception.
Now, it is not absolutely necessary to create instance method inside the newly created custom exception class. We can also create static method in it and call it whenever necessary.
<?php class FileNotReadableException extends Exception { private static $fileWithError = 'Default'; public function __construct(string $fileName) { self::$fileWithError = $fileName; parent::__construct("The provided file could not be read."); } public static function customMessage() { echo "File with Error While Reading is- " . self::$fileWithError . " \n"; } } class HandleFileOperation { public function checkFileIsReadable($file) { if (!is_readable($file)) { throw new FileNotReadableException($file); } else { // process file } } } $objCustomException = new HandleFileOperation(); try { $objCustomException->checkFileIsReadable("processFile.php"); } catch (FileNotReadableException $e) { echo FileNotReadableException::customMessage(); }
Above code will execute and will give same output like the previous example. Only difference is that we used here static methodolgy to write our code and tried to get the advantages of static.
Now, if you worked on modern framewporks like Laravel, Symfony then you must have seen tons of custom build exceptions. Like in symfony few examples are- AuthenticationException, AuthorizationException, BadResponse, BadMethodCallException, SecurityException etc.
Let’s understand the reason behind creating authentication exception and different methods defined inside it.
This exception is used inside authenticate middlware and if current user is unauthenticated then user will be presented with this exception. This exception is thrown inside unauthenticated() method which is defined as protected because based on the requirements we can modify the method inside child class by defining this method. This gives us more flexibility to write our authentication class by extending to this Authenticate class.
Conclusion:-
Exceptions are the powerful mechanism to handle all the errors in the runtime. As mentioned with above information, it can be occurred with many reasons. So handling at the time of writing code is the proficient way to halt unexcepted error to occur.