What is the best practice for throwing an Exception in the following situation:
My URL structure is:
/articles/view/id/1
My Controller:
AticlesController
And this controller loads a Mapper model:
Application_Model_Mapper_Articles
In this model I aggregate all kinds of data. I check several criteria in this model to decide between throwing a 404 error or showing the article.
If I decide to throw the error. How should I do it?
My first guess was throwing it from within the model. But there is no default 'Model_Exception' class and there is a 'Zend_Controller_Action_Exception'. Should I just throw this exception from within the model? Or should I pass the error message back from the model to the controller and then throw the error?
Model itself should not interfere with the FrontController, so yes, throw the exception from the controller.
You may throw an exception from the model (not Zend_Controller_Action_Exception, but some that more precisely describes your problem), catch it in the controller and on that base decide if you're gonna throw Zend_Controller_Action_Exception or not.
You could create an Application_Model_Mapper_Articles_Exception, and you could either choose to handle that in your controller and throw exceptions to the error controller, or use your exception code to designate the type of HTTP response code to set.
Related
I'm using a new API and I want to handle exceptions specific to it, and return the data from the exceptions to JS function that made a request. The thing is - I have a fatal_handler registered with register_shutdown_function in the program, and I want to avoid it for these exceptions, because It won't let me return the necessary data to the JS function, and I don't want to mess with this specific handler because it's more general.
I managed to override it with set_exception_handler, but I assume it will catch other unhandled exceptions as well.
Is there any way to define the instance of the exception (e.g AException) that will be handled in set_exception_handler(), same as in a catch block?
My only idea was to check the type of the exception object I'm getting to the handler function (with instanceof, and rethrow it if it's not the type I'm looking for.
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.
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.
I am creating a class that validates strings. There are many reasons why the string might not pass.
Would it make more sense to throw an exception, or return false/error code? Pros/cons?
validators should not throw exceptions, as failing a validator is not an "exceptional" event.
the rest of your code should throw exceptions if it gets bad data.
when you run a validator function you are clearly prepared to handle any problems detected with a simple test. wrapping everything in a try/catch block and stopping all execution only to try to recover is overkill. Just use and if statement, and be prepared to show the user some error messages.
Return false.
Exception is EXCEPTION, and should be thrown in exceptional cases only, when script can't continue execution.
Throwing an exception seems a bit extreme, as a string not validating isn't really an exceptional event as far as a string validation suite is concerned.
As such, I'd have thought that returning false would seem the most logical solution. Additionally, you could also pass back a meaningful textual error via a reference variable, if this makes sense as far as your implementation is concerned.
For example:
// In the class definition...
public function validateSTring($stringToValidate, &$errorString=null) {
// If an error occurs...
if($errorString) {
$errorString = 'Something went wrong along the way.';
return false;
}
}
// When calling...
$errorString = '';
$validationSuite->validateString($stringToValidate, $errorString);
It's argued that validator class should return a bool. isValid(string $someData): bool and it's not an exception if the validator determines "false" is the response for "isValid". This is a solid approach, but you lose out on knowing what went wrong in the caller of the validator.
The choices are:
Validator doesn't throw exception and just returns bool, but has to log the errors as it knows specifically what went wrong (invalid email, missing mandatory value, etc)
Validator does throw an exception with the error data in it for caller to log and handle
The issue with "1" with validator logging, is validator doesn't know the context of the issue. Usually numerous things will call a validator class as they are reusable, so validator doesn't know who called it to log e.g. "Factory XYZ failed to create object due to invalid email address".
Whereas if validator throws exception with the error info in then caller can log those errors with context of what went wrong and where in the log. Sure you can log errors in both validator and then in caller with more context, but then you have multiple logs and not naturally related. Is this all worth it just to have validator return bool?
The other issue with "1" just return bool is you are logging in validator, and I'd rather lose some stringent "must return bool" and keep validator simple and not be doing logging with weak information.
While returning "false" from a validator class arguably isn't an exception, the caller not being able to perform the task due to validation error is an exception, so validator throwing one is about "we have an exception because something is not valid".
I think it's really useful for validator to throw an exception with the error info as a new array (like extra data on a specific exception class extending Exception etc).
And instead of calling the validator method isValid() which does kinda require a bool response, call it validate() and wrap the call in a try/catch.
I am not sure if Exceptions work the same way in each language, but I am using PHP and I was wondering when I'm doing something like this:
if (!$this->connection[0]->query($this->query))
throw new QueryFailedException($this->connection[0]->error);
Is there a need to supply a code in the second parameter? For example:
if (!$this->connection[0]->query($this->query))
throw new QueryFailedException($this->connection[0]->error,123);
Now the code is 123... I can't think of a need for this. Is there one? In this case the message contains the query, exception name is QueryFailedException which explains the exception type, the exception itself contains file, line and stack trace, so, I can't think of anything where you could use the code for something useful.
The error code was a feature used when there was no object oriented language. The only thing that could aid you to understand what went wrong was the error code. In an object oriented language, the object IS your error code.
Unless, in specific cases, more than one thing can throw the exact same error AND they are treated in different ways, drop it.
Also, you would provide much better explanation to whomever is debugging your code if you left a message instead of a meaningless error code, so if you feel like the exception needs more information, fill the Error Message field instead.
The error code is a field that can be used to provide more detailed information. If for example you have two things that can generate the same exception, the code could be used to give more detail.
If you have an "error source" that works on error codes and you "promote" it to exceptions you can include the actual error code in the exception. a) it does no harm and b) maybe you do not want to have an exception class for each single error code that may or may not occur (and virtually no one cares for in a running system).
Let's take the MySQL server errors as an example. You could create one class for each of those codes
class MySQLException_ER_HASHCHK extends MySQLException
class MySQLException_ER_NISAMCHK extends MySQLException
class MySQLException_ER_NO extends MySQLException
class MySQLException_ER_YES extends MySQLException
class MySQLException_ER_CANT_CREATE_FILE extends MySQLException
class MySQLException_ER_CANT_CREATE_TABLE extends MySQLException
class MySQLException_ER_CANT_CREATE_DB extends MySQLException
class MySQLException_ER_DB_CREATE_EXISTS extends MySQLException
class MySQLException_ER_DB_DROP_EXISTS extends MySQLException
....
but in reality ...who cares? Who's really gonna catch them individually? In almost all cases there will only be a catch(MySQLException $mex) in the app's code and maybe, just maybe it's looking for one specific code where it makes little to no difference for the coder whether there are two catch-blocks or an if/switch block. Now you have a lot of "dead" classes and no one -except the parser- gives a damn about them. (on the other hand "everything worth doing is worth overdoing it")
And even if you do provide some granularity I think it makes little sense to go beyond e.g. having one exception class for each SQLState (does that make sense? sqlstate? don't know, just an example)
class MySQLException_HY000 extends MySQLException
class MySQLException_HY001 extends MySQLException
class MySQLException_XA100 extends MySQLException
class MySQLException_XA102 extends MySQLException
And then again you probably want to include the error code - why lose this information even though/even if your code usually doesn't evaluate it?
If you can, it is very good to set in an exception code.
That is if you don't change your code to throw different exceptions based on the data you get from your database.
The error code, in OOP is the Exception Class Name itself, so that you can interpret each of them in just one try but with multiple catch clauses.
try {
// code here
} catch (AccessDeniedException $e) {
// do something
} catch (Exception $e) {
// do something else
}