How to structure a simple PHP Exception class - php

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.
}

Related

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.

In PHP is there a way I can avoid repeating the same try / catch code in multiple methods of a class?

I've been searching for an existing question that already asks this, but I wasn't able to find any questions that quite ask what I'm trying to figure out. The most similar question I could find was this: php 5.3 avoid try/catch duplication nested within foreach loop (code sandwich)
Okay so the place I work at has a web application with a PHP back end. We use an MVC type structure. I'm writing a controller that has multiple methods and in each of my methods I'm wrapping my code with identical try / catch code. In the catch, I pass the exception, a reference to the class, and a reference to the function to a method that builds an error message so that the error messages are formatted the same across the application. It looks something this:
class MyController {
public function methodA() {
try {
// code for methodA
} catch(Exception $e) {
$errorMessage = Tasks::buildErrorMessage($e, __CLASS__, __FUNCTION__);
throw new Exception($errorMessage);
}
}
public function methodB() {
try {
// code for methodB
} catch(Exception $e) {
$errorMessage = Tasks::buildErrorMessage($e, __CLASS__, __FUNCTION__);
throw new Exception($errorMessage);
}
}
public function methodC() {
try {
// code for methodC
} catch(Exception $e) {
$errorMessage = Tasks::buildErrorMessage($e, __CLASS__, __FUNCTION__);
throw new Exception($errorMessage);
}
}
}
So the buildErrorMessage function prevents each method from repeating the code that formats the error message, but there is something that really bothers me about have the same code spread through out every method in the class. I know that PHP doesn't support python-like decorator syntax, but just to demonstrate what I'm envisioning conceptually; I want the code to behave something more like this:
class MyController {
#DefaultErrorHandling()
public function methodA() {
// code for methodB
}
#DefaultErrorHandling()
public function methodB() {
// code for methodB
}
#DefaultErrorHandling()
public function methodC() {
// code for methodC
}
}
Where the #DefaultErrorHandling decorator would wrap each method in that standard try / catch. Is there a way I could achieve this behavior so I don't have to have all of these methods that have repeated code? Or am I thinking about error handling incorrectly?
Thanks to anyone who takes the time to answer this.
Have you looked at a writing a custom exception handler and using set_exception_handler?
What you are doing seems a bit like reinventing the wheel. Does the Exception not already have the info you are collecting in the trace? See: Exception::getTrace
Maybe buildErrorMessage does more? Anyway, I assume a custom exception handler is what you are after.
Not sure if there is a better way to solve this or not, but I created a logging class that formatted the log for me. Then just called this in my catch block.
To log the correct Class and Method, I the debug_backtrace() function. See this answer for more information.
Entry point that calls controller methods can wrap those calls with try / catch. That being said, if you are planning to use different type of error handlers on those methods then you can implement something in your base controller (or use trait) that keeps track of which handler should be invoked on each particular method. Something like
<?php
class MyController extends Controller
{
function __construct()
{
$this->setActionErrorHandler('function_name', 'handler');
}
}
Or just call it at the beginning of action method body. Keeping this type of configuration within class itself will help with readability. Not as neat as python example but better than somewhere in configuration files.
More generic error handlers can be implemented in php by using set_exception_handler mentioned by others.
I'm not really getting why there is such a requirement.

Symfony2 Exception class, Why use throw new $class?

I'm looking at Symfony2 classes and I found something like this
try {
return $this->parseSelectorGroup($stream);
} catch (\Exception $e) {
$class = get_class($e);
throw new $class(sprintf('%s at %s -> %s', $e->getMessage(), implode($stream->getUsed(), ''), $stream->peek()), 0, $e);
}
Why they use
$class = get_class($e);
throw new $class
such syntax. What is the purpose of that?
I'm not the original author of that line of code so I can only assume why this was done.
As the code shows, the standard message of the exception is being extended with additional information of the string handling class (getUsed, peek - sounds like a stream buffer/parser/scanner/peeker).
The Message is edited and then a new object of the same class is being thrown.
Generally: When you have a class name in a variable and want to create a new instance of that class, you can simply use:
$className = "ClassName";
$instance = new $className();
This is done here with the catched exceptions classname, see get_class.
Further Note: This code is conceptually broken because it uses a class with an undefined interface for it's constructor. It then makes use of the constructor function without knowing anything about it's constructor.
There might be some information hidden that such a case is not to be expected to happen though. So this is merely a further note. You should have concrete reasons to do something like that, so this has been done for a reason and there might be some design decision which is not documented by the some lines of code you've posted. So handle with care.

Why use multiple PHP Exception classes

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)

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