I have some code that makes db calls and network requests and I have it wrapped in a try/catch. The problem is that I can never catch the exceptions, and they don't appear to be fatal exceptions:
try {
// make db requests and network calls
} catch (Exception $e) {
// handle exception
}
Namely, I encounter exceptions such as these:
[Illuminate\Database\QueryException]
[PDOException]
[InvalidArgumentException]
Is there a way to catch these exceptions? Do I need to be explicit for each possible type of exception object (meaning I must create many try/catches), or is there a recommended way of catching non fatal exceptions?
Make sure you're using your namespaces properly, by including the Exception class at the top of your controller like this:
Use Exception;
If you use a class without providing its namespace, PHP looks for the class in the current namespace. Exception class exists in global namespace, so if you do that try/catch in some namespaced code, e.g. your controller or model, you'll need to do:
try {
//code causing exception to be thrown
} catch(Exception $e) {
//exception handling
}
If you do it like this there is no way to miss any exceptions.
Otherwise if you get an exception in a controller code that is stored in App\Http\Controllers, your catch will wait for App\Http\Controllers\Exception object to be thrown.
Related
As far as I know, the exception handler should handle any exceptions in any part of my script (classes, functions, etc.).
My exception handler doesn't catch any exceptions although, I tried many times and versions. Can someone help me find the problem? I use nginx & php-fpm (latest).
<?php
require_once 'vendor/autoload.php';
set_exception_handler(['\App\Core\ExceptionHandler','handler']);
The exception handler -
namespace App\Core;
class ExceptionHandler
{
public static function handler(\Throwable $e)
{
.....
}
}
I managed to solve the problem by using proxy class.
So, all of my calls to the controllers wrapped by a main controller class with try-catch block.
So, when our script throws exception, we can send it to our exception handler.
I think it's a better solution after all.
Now what I generally do when writing code is something like this
function changeBookAuthor(int $id, string $newName){
if(!$newName){
throw new MyAppException('No author name was provided');
}
$book = Books::find($id);
if(!$book){
throw new MyAppException('The provided book id could not be found');
}
}
in the laravel doc we see:
https://laravel.com/docs/5.4/errors
public function report(Exception $exception)
{
if ($exception instanceof CustomException) {
//
}
return parent::report($exception);
}
Now how to I properly handle the exception? they are all the same exception and they have no code neither. Should I provide an error code?
the problem with php exception is that they use integers. Is quite annoying imho. Better would be 'changeauthor_bookid_notfound' as code instead of a random number. Should I create an exception class for each single exception? e.g. not reuse MyAppException that seems a bit tedious. I would have a trillion classes.
Now if for a special exception I want special handling, with my code, I cannot easily do it. I have no code to check for (e.g. $exception->code == 3331 then do special) and I don't have custom exception classes neither
what is a proven good solid way to handle this case?
code, new class on each error, something else all together?
and if provide a code, what is a nice way to do it?
The "proper" way to do it would be to define either a custom Exception class for each exception, or to define custom exceptions based on the type of error being thrown, however realize that Laravel already has many built in exceptions and mechanics for handling the use cases you outlined.
For instance, in the case of the "Book Not Found" exception, rather than manually triggering an exception yourself, you could use Books::findOrFail($id); which throws an instance of ModelNotFoundException when appropriate.
Also, in PHP there is no need to handle exceptions for unprovided arguments. Unless expressly denoted as optional, all method arguments are required, and Laravel will throw a PHP exception if an argument is missing.
Additionally, Laravel provides the abort() magic method which throws a HTTP error along with a custom error message and can be used like so:
abort(418, "I'm a teapot...")
So, if you must reinvent the wheel, the proper way is to define custom exception classes and define the custom handlers for those classes, but realize that Laravel already has many built in tools for managing exceptions without needing to do so.
Recently I have been developing in Zend Framework. I came into a confusion during exception handling.
Can anybody let me know where is the best place to handle exception? Whether it is model or controller? It may be in terms of performance or usability or anything else.
If we want to catch all kinds of exceptions, we better enable our model to throws exception. You can read this post also link
You should handle exceptions in your controllers because sometimes the error messages of exceptions should be passed on to views. To avoid the dependency between models and views you should handle exceptions in your controllers.
Zend Framework all ready handles exceptions through the inbuilt errorController. You can enable it by placing the following line in your config file.
resources.frontController.throwExceptions = 0
Also, if you want to handle exceptions your self, rather then handling them at different places you can just handle them at one place. Something like below.
Tell Zend Framework to not handle exceptions. Do this in your application.ini
resources.frontController.throwExceptions = 1
Do following in your Bootstrap class.
Define a custom method to handle exceptions.
public function __handleExceptions(Exception $e){
//render a view with a simple error message for the user
//and send an email with the error to admin
}
Override the _bootstrap() and run() methods of Zend_Application_Bootstrap_Bootstrap in your Bootstrap class and catch the exceptions thrown during the bootstrap process or while running the application and call your exception handler as shown below.
protected function _bootstrap($resource = null)
{
try {
parent::_bootstrap($resource);
} catch(Exception $e) {
$this->__handleExecptions($e);
}
}
public function run()
{
try {
parent::run();
} catch(Exception $e) {
$this->__handleExecptions($e);
}
}
Now all your exceptions will be handled from a single place.
I'm building a custom autoloader based on Zend Framework's autoloading (related question here).
The basic approach, taken from that question, is
class My_Autoloader implements Zend_Loader_Autoloader_Interface
{
public function autoload($class)
{
// add your logic to find the required classes in here
}
}
and then binding the new autoloader class to a class prefix.
Now what I'm unsure about is how to handle errors inside the autoload method (for example, "class file not found") in a proper, ZF compliant way. I'm new to the framework, its conventions and style.
Do I quietly return false and let the class creation process crash?
Do I output an error or log message somehow (which would be nice to pinpoint the problem) and return false? If so, what is the Zend way of doing that?
Do I trigger an error?
Do I throw an exception? If so, what kind?
ZF itself uses two different approaches:
Zend_Loader (the old autoloading mechanism) throws a Zend_Exception in case something's wrong
Zend_Loader_Autoloader returns false when the used registered autoloader returns false
The Zend_Loader_Autoloader doesn't catch any exception thrown in the used autoloader to eventually your custom exception would bubble up through the Zend_Loader_Autoloader. I personally just return false in case I'm not able to load a requested class.
That depends on the kind of error. I'd consider it a fatal error if a class cannot be loaded. Thus I'd throw an Exception, e.g.
class My_Autoloader_Exception extends Exception {}
You will find that ZF uses a lot of custom Exceptions on the package level and also provides a class for this to extend from (though I'd consider this optional).
Incidentally, there is a usage example of Zend_Exception with their autoloader:
try {
// Calling Zend_Loader::loadClass() with a non-existant class will cause
// an exception to be thrown in Zend_Loader:
Zend_Loader::loadClass('nonexistantclass');
} catch (Zend_Exception $e) {
echo "Caught exception: " . get_class($e) . "\n";
echo "Message: " . $e->getMessage() . "\n";
// Other code to recover from the error
}
I used to use this when I wanted to trigger errors in PHP, coming from a PHP4 background. Note I had my own set_error_handler() for handling these errors.
if ($error) {
trigger_error('Sorry, error has occured');
}
I can't remember where, but sometime ago someone told me I should be 'using exceptions'. As I'm re factoring a lot of my old code, I figured now is the time to get some good advice on my error handling implementation.
Now that I'm using PHP5 (and a bit smarter than I was when I wrote the older code), is my trigger_error() just an old way of doing things, and if so, what is the best way to handle errors in PHP5?
Yes, you may want to start looking into the PHP 5 exception model. Remember though that just because something is new doesn't mean that you must adopt it. Only adopt those features that you need and make sense in your domain.
That being said, I feel that exceptions are a good concept to grasp and even if you decide not to adopt them you will be all the better for the experience.
I would like to suggest that you read PHP: Exceptions - Manual:
PHP 5 has an exception model similar
to that of other programming
languages. An exception can be thrown,
and caught ("catched") within PHP.
Code may be surrounded in a try block,
to facilitate the catching of
potential exceptions. Each try must
have at least one corresponding catch
block. Multiple catch blocks can be
used to catch different classes of
exeptions. Normal execution (when no
exception is thrown within the try
block, or when a catch matching the
thrown exception's class is not
present) will continue after that last
catch block defined in sequence.
Exceptions can be thrown (or
re-thrown) within a catch block.
I would also encourage you to read What Is an Exception? (Note this is a Java tutorial but the concepts are universal)
When an error occurs within a method, the method creates an object and hands it off to the runtime system. The object, called an exception object, contains information about the error, including its type and the state of the program when the error occurred. Creating an exception object and handing it to the runtime system is called throwing an exception.
Edit: In order to implement a global exception handler (basically in order to establish a default exception handler that will handle previously unhandled exceptions) you will want to us the set_exception_handler function.
Using exceptions is the object-oriented way to trigger and handle your own application errors.
The PHP manual topic on exceptions is probably a good place to start.
Here is a small example:
function doSomething() {
if ($error) {
throw new Exception('Some descriptive error message.');
}
}
try {
doSomething();
}
catch (Exception $e) {
die('<p class="error">' . $e->getMessage() . '</p>');
}