Why use multiple PHP Exception classes - php

I admit I do not use Exceptions a whole lot and they are at time hard for me to grasp 100% in PHP, this could be partially because PHP does not have the best error => Exceptions support but none the less I do not know much about them.
Take for example this code below, it has 4 different Classes defined that do nothing but extend a base Exception class. I am just curious why one would not just call an Exception and why they have all these separate classes.
I assume there is a good reason?
class OptimizeImageException extends Exception {};
class FileNotFoundException extends OptimizeImageException {};
class FileNotImageException extends OptimizeImageException {};
class ModuleNotFoundException extends OptimizeImageException {};

By having multiple Exception classes, you can pick out which one you're interested in when catching them.
<?php
class OptimizeImageException extends Exception {};
class FileNotFoundException extends OptimizeImageException {};
class FileNotImageException extends OptimizeImageException {};
class ModuleNotFoundException extends OptimizeImageException {};
try {
throw new FileNotImageException();
} catch (FileNotFoundException $x) {
echo "NOT FOUND!";
// do something about it
} catch (FileNotImageException $x) {
echo "NOT IMAGE!";
// do something about it
} catch (Exception $x) {
echo "UNKNOWN EXCEPTION!";
// do something else about it
}
This is a trivial example, but say you have a function loadImage() which is supposed to load an image. If the function fails, you can handle different failure scenarios differently. If you always throw a basic Exception, you only know something went wrong. You don't know what went wrong, so you can't have different recovery responses based on different scenarios, not without using another mechanism (which then makes exceptions rather weak).

You need to have different exception classes to be able to find out what actually happened in case that some particular exception could be handled.
Like:
try {
// do something
} catch (OptimizeImageException $e) {
// image cannot be optimized. left it as is and log the error message
}
In the code above you're handling one particular exception case, that can be processed right here and right now to move your application flow as expected. Other possible exceptions will go upper.
If you had only one exception class like MyAppException then all you could do is just catch it, check the message (which is weird) to realize what actually happened and if you cannot handle it - rethrow exception. As you can see this way your code would be a bit hackish and unmaintainable (you cannot change exception message)

Related

Symfony 4 custom exception handler for certain controllers

From my understanding there can only be one exception handler which will catch all unhandled exceptions. However, is there an elegant way to have a specific exception handler for Controllers A and B, and controllers C, D, etc. would be handled by default exception handler?
I don't think this is possible by default, other than creating a kernel eventlistener. However, you can create something simple yourself.
In a Controller Method, you might could do something like
public function index()
{
try {
// Do normal logic here.
} catch (\Exception $e) {
// Do whatever you want with any exception.
// Or Call your exception handler: MyExceptionHandler::handle()
}
}
You can also create a custom AbstractController so it might be a bit simpler. In which you extend the render function, so you abstract that logic away

How does Throwable interface work inside catch ()?

Interfaces cant be instantiated , and interfaces do not have methods bodys so how that code works ? (to manage Exception and Error at same time in php 7 we use Throwable cause Exception and Error both implement a new interface )
try {
// Code that may throw an Exception or Error.
} catch (Throwable $t) {
// Handle exception
}
Exception and Error implement the interface Throwable. In fact there is a whole hierarchy for Errors in PHP. You can catch a specific type of error or you can go up the tree and catch more generic errors. Throwable is the base interface and is going to catch all errors in the hierarchy.
When type hinting with OOP you do not need to use the exact type. You can use the base interface or parent type. For example.
interface MyInterface {
}
class A implements MyInterface {
}
function doSomething(MyInterface $obj) {
// something
}
doSomething(new A);
This code works and accepts the object of class A even if the type expected is an interface MyInterface.

Does it necessary using sef-defined Exception

As we all konwn,PHP have a class named "Exception"to handle the unexcepting situation.I usually find that someone like self-define a new exception class which extend the class "Exception". This new exception class do not rewrite or add any function.It just state a children class of the class "Exception".
so,I doubt that if it is necessary self-define a new Exception class in my project?In the past,I used the class "Exception" in anywhere.
It is not necessary, but it might be very convenient: If you have different kinds of exceptions, you can handle them differently when you catch them:
try {
...
} catch (SpecificException $e) {
// Do something specific here
} catch (SomeOtherException $e) {
// Here you can do something else
} catch (\Exception $e) {
// The rest...
}
The main reason to define an exception in that way is to help with debugging and error handling. Not only is something like NetworkException more informative, but you can also catch that type of exception when it occurs, so you can deal with different types of exceptions in different ways. Some may be temporary, so you might catch them and ask the user to try again later, for instance.

How to structure a simple PHP Exception class

Hi devs
I have a simple PHP OO project. I have an exception who appears 2 times.
Something like :
if (!$x) {
throw new Exception("Don't use this class here.");
}
I want to dev a class in order to edit this code like that :
if (!$x) {
throw new ClassUsageException();
}
How to dev the Excpetion class with default Exception message ?
Thanks
I'd advise creating new exception classes sparsly. It is no fun to check a multitude of exceptions left and right. And if you really feel the need, check what kinds of exceptions are already defined and where in that hierarchy your exception will fit and then extend that class, i.e. give the developers a chance to catch a (meaningful) range of exceptions without having to explicitly write one catch-block after the other.
I'm really not sure what you're trying to achieve here with Don't use this class here. but it could be an InvalidArgumentException (or something derived from that exception, if you really must). There are other mechanisms to prevent an instance of a certain class at a specific place though.
You can extend the Exception class
<?php
Class ClassUsageException extends Exception {
public function __construct($msg = "Don't use this class here.", $code = 0) {
parent::__construct($msg, $code); //Construct the parent thus Exception.
}
}
try {
throw new ClassUsageException();
} catch(ClassUsageException $e) {
echo $e->getMessage(); //Returns Don't use this class here.
}

PHP: Namespaced classes, class loading and exceptions causes weird behaviour

I witnessed some strange behaviour regarding PHP's exception handling in a recent project. Case goes as follows.
In my app, I use namespaces. All classes are in individual source code files. The code relevant to this particular case, is spread over 3 classes.
The "outermost" class is a dispatcher (or router), which wraps the dispatch call inside a try-catch block. The dispatched request, calls a method in a third class, which runs code (wrapped in a try-catch block), which causes an exception.
Because I had omitted a use Exception; statement in the class where the error happens, the thrown exception trickles all the way back to the outermost layer (the dispatcher), where it is caught - causing me to scratch my head why the catch around the code causing the error isn't working.
To me this seems strange. Logically, PHP should in this situation (IMO) throw a Class not found exception/error, leading me to the actual error in my code, instead of trying to "stay alive" as long as possible.
Should this be filed as a bug, or is this expected behaviour?
Edit: Code example
File: class-a.php
<?php
namespace hello\world;
class classA {
protected $b;
public function __construct() {
$this->b = new \hello\world\classB();
}
public function doSomething() {
try {
$this->b->throwException();
} catch (Exception $e) {
}
}
}
File: class-b.php
<?php
namespace hello\world;
class classB
{
public function throwException() {
throw new \Exception("bar closed");
}
}
File: run.php
<?php
include 'class-a.php';
include 'class-b.php';
$a = new \hello\world\classA();
$a->doSomething();
ClassB throws an \Exception in ClassB::doSomething(), for which ClassA has a catch-clause, but because ClassA doesn't declare use Exception or catch (\Exception), the catch doesn't match and execution ends with a Uncaught exception error1. But in my opinion, it should cause a Class not found error.
I might be expecting too much of the permissive PHP compiler, but it would help in tracking down silly errors that should be easy for the compiler to spot.
1 If the $a->doSomething() in run.php was surrounded by a try..catch clause, the Exception would (or at least could) be caught there, since it trickles down the stack.
PHP's exception catching mechanism does not validate that the class you catch actually exists.
It exhibits the same behavior when using typehinting in functions, so I suspect it merely converts the exception/function type hint into a string or something and compares that with the type of the relevant object.
Whether this is a bug or not is questionable. Personally I think it should be classified as a bug, but PHP has all sorts of wonky behaviors :D

Categories