Exception Handling in Zend framework - php

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.

Related

php set_exception_handler() not catching exceptions

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.

Forced user logout in case of internal errors in cakephp3.0

I am using cakephp 3.0 ,In my application I want forced user logout or clear session in case if any internal error occurs,How can I accomplish it. Can I make any changes in the error controller and will it able to catch the specific internal errors.
CakePHP uses the ErrorController to render HTTP responses for both unhandled exceptions and fatal errors. Keep in mind that it's also used for 404 not found exceptions.
You can logout the user in ErrorController in the beforeFilter event, and render the error message as normal. Afterwards their session will have ended.
I give you a warning. The ErrorController should be kept as simple as possible. Should not perform heavy logic. The reason is very simple. If you generate a fatal error inside ErrorController it creates an endless loop.
Most people configure their AuthComponent in their base AppController which you should never extend as the base class for ErrorController.
That means you have to configure the AuthComponent separately in your ErrorController and hope it never fails and you keep the configuration consistent with what you have in AppController.
If you go that route. Also wrap your code in a try/catch block to prevent exceptions from being thrown from inside the ErrorController.
For example;
public function beforeFilter(Event $event)
{
try {
$this->Auth->logout();
}catch(\Exception $ex) {
// prevent endless loop
}
}
Alternative perform a 302 redirect:
It's better to keep ErrorController as vanilla as possible and not load the AuthComponent inside it. I assume you have a controller already set up for logging users in and out. Add a new route for that controller called "forced_out", and then redirect the URL to that route when there is an uncaught exception. Inside the action for "forced_out" you can log the current user out.
Create a new error handler class like this.
class ForceOutErrorHandler extends ErrorHandler {
protected function _displayException($exception)
{
// restore the old handler
(new ErrorHandler(Configure::read('Error')))->register();
throw new RedirectException(Router::url([
'controller'=>'Users',
'action'=>'forced_out'
));
}
}
Now register that error class only when a user is signed in. You can do this in the beforeFilter of your AppController like this:
public function beforeFlter(Event $event) {
if($this->Auth->user()) {
(new ForceOutErrorHandler(Configure::read('Error')))->register()
}
}
Note: I'm not sure if CakePHP will catch the redirect exception from inside the error handler like that or not. You might have to use header(); die() as a last try.

The proper way to do exception handling

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.

Best way to catch Doctrine Exceptions in Codeigniter

What do you think is the best way to catch all doctrine 1.2 ORM exceptions in codeigniter framework, i would not like to wrap the entire index.php with a try catch, but neither to do a try catch before and after every query,
Well, first, you'll have to wrap around only single line in index.php. And actually, this might be good in case you have exceptions you don't want to show (e.g. in production environment).
The second point here is that your database-related code should be concentrated in models. So you might introduce helper class, which is something like
class SafeQueryHelper{
public static function safeQueryRun(Doctrine_Query $q, array $parameters, $hydration=Doctrine_Core::HYDRATE_RECORD){
try{
return $q->execute($parameters, $hydration);
}
catch(Exception $e){
//Handle yur exceptions here
}
}
}
Than you'll just replace $query->execute($params,$hydration) in all your models to SafeQueryHelper::safeQueryRun($query,$params,$hydration). Don't forget to load it with $this->load->helper('SafeQueryHelper') or through the config.
For record methods like update and delete - you'll have to wrap it in try .. catch.
Well, and if you don't have your database-related logic concentrated in models... That changes nothing, actually, but that means that you have poorly-designed application that violates the essential priinciple of MVC pattern, so start refactoring.
The last possible solution - is to hack into Doctrine core classes (specifically into Doctrine_Connection) and wrap into try ... catch lines that perfrom actual quering. But that's a bad idea, I really wouldn't do that.
A little update: as all Doctrine entity objects are subclaeses of Doctine_Record youmay extend SafeQueryHelper with methods for wrapping save, delete etc:
public static function SafeSave(Doctrine_Record $entity){
try{
$entity->save();
}
catch(Exception $e){
//catch it
}
}
Than replace $entity->save() with SafeQueryHelper::SafeSave($entity)

Proper error handling in a custom Zend_Autoloader?

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
}

Categories