Throwing custom exceptions without messages - php

I haven't uset custom exceptions before, and now it appears that I might need them but I'm not sure I understood correctly how are they supposed to be used.
Say I have a custom exception like this:
class not_found_exception extends exception{ }
Then I have a bunch of request handler functions (I think they are called controllers in the wild). And each function can throw different types of exceptions. If the URL doesn't match it throws my custom exception, the script will catch that type of exception and skip to next request handler if it's caught. But other types of exception are not supposed to be caught because they mean that the url matches but there's some other error that should be displayed.
The thing is that my custom exception doesn't need an error message because it would not show up anywhere because its supposed to be caught, but other exceptions do. So is it ok to just throw an empty not_found_exception exception?

The short answer is simply: yes. That would be ok.
For further information about best-practices regarding Exception I'll refer you to this blog. It may be written for .NET but the theories can still be applied to PHP.
https://blogs.msdn.microsoft.com/kcwalina/2007/01/30/how-to-design-exception-hierarchies/

Related

Laravel stops executing when an Exception occurred and displaying the message using some default template - Handling exceptions in laravel

I am using latest version laravel(5.6)
Now in my code whenever an exception occurs laravel treating it as a fatal error, stop executing instantly and displaying the error message in some template.
But I don't want that, I want to handle exceptions and display some custom error messages
I found some ways like
changing the APP_DEBUG value in the .env file to false. But this also displays another
page with the message "whoops!some this want wrong";
In Handler.php which is in app/Exceptions, I had put some exceptions in not report zone. But the app is still reporting them
Custom HTTP Error Pages
Laravel makes it easy to display custom error pages for various HTTP
status codes. For example, if you wish to customize the error page for
404 HTTP status codes, create a resources/views/errors/404.blade.php.
This file will be served on all 404 errors generated by your
application. The views within this directory should be named to match
the HTTP status code they correspond to. The HttpException instance
raised by the abort function will be passed to the view as an
$exception variable.
https://laravel.com/docs/5.6/errors#custom-http-error-pages
Really you want to be handling your exceptions. Wrap the code in a try catch and you can do all manner of things (e.g. email / slack / log). Once you have handled the exception you can still use custom http error pages inside the catch so the end user get's a friendly message on a nicely designed page. There is even a report helper built in to allow you to externally log and continue on processing the code.
#Devon's above answer re: Custom HTTP Error Pages gets you exactly what you want also.
Please note few important points :
The App\Exceptions\Handler class is where all exceptions triggered by your application are logged and then rendered back to the user. This class has two method report() and render(), both has their own responsibility.
The report method is used to log exceptions. By default, the report method passes the exception to the base class where the exception is logged. However, you are free to log exceptions however you wish. For example, if you need to report different types of exceptions in different ways, you may use the PHP instanceof comparison operator
The render method is responsible for converting a given exception into an HTTP response that should be sent back to the browser. By default, the exception is passed to the base class which generates a response for you. However, you are free to check the exception type or return your own custom response.
As in your case you want to return custom message for exception, inside render() you may use the PHP instanceof comparison operator and return you own logic.
Example :
if($exception instanceof PostTooLargeException || $exception instanceof FileException){
return response()->json([
'error' => true,
'error_message' => "The file you are trying to upload exceeds the maximum limit. Please try to upload a smaller file."
],200);
}
Go through https://laravel.com/docs/5.6/errors for more datails

Is it possible to make PHP exceptions non-fatal?

I wrote a class whose methods frequently throw a number of Exceptions--for example, a NoResultException if the given user ID doesn't correspond to a user, a BadTokenException if the token was wrong, an EmailTakenException if the e-mail address is already registered, etc.
I am trying to write a test program using it really quick. I was feeling lazy and I didn't want to write try/catch blocks. I probably will now, but I still have to ask: is it possible to change PHP's behavior and make it so that Exceptions don't produce fatal errors? In other words, can I make my script catch the Exceptions and output them using the default exception handler (since I'm using XDebug and the backtrace is nice), but allow the script to finish executing? Then I can just see the message of the error (like "The e-mail address is already taken") without stopping the rest of the page from being printed.
Thanks.
use trigger_error instead. it throws non-fatal errors
trigger_error("Custom Error", E_USER_ERROR);
display it via set_error_handler()
see
http://us1.php.net/trigger_error
and
http://us1.php.net/set_error_handler
You can only make exceptions non-fatal if you catch them through try/catch blocks and you've just said that you're too lazy to do that? This makes no sense. You either use trigger_error or you add try/catch blocks.
You can have uncaught exceptions be non-fatal by creating an set_exception_handler function to handle them. Most of the time I just show a HTTP 500 system error page. If there is a way to recover (Which I'm not sure why you wouldn't do it in a try/catch) you can do there by looking at the Exception class and the error code number in the exception.

custom error page - can't get into handler

I'm trying to add my custom pages. I'm using Kohana 3.3. The official documentation states that I should ovveride the method hander of native Kohana_Exception class. This is pretty easy to do so I've done that. Now I'm expecting that Kohana would call that method every time an exception or an error occurs. But this is not the case. I've found 2 catch blocks where an exception is caught inside execute_request method of Kohana_Request_Client_Internal class.
First catch
catch (HTTP_Exception $e)
{
// Get the response via the Exception
$response = $e->get_response();
}
Second catch
catch (Exception $e)
{
// Generate an appropriate Response object
$response = Kohana_Exception::_handler($e);
}
As you can see, none of the catch blocks calls handler method overriden by me.
Setting your own exception handler set_exception_handler has no effect since it is applied only to uncaught exceptions and the exceptions like 404 are thrown and caught.
No problems with run-time errors though. This block catches them and explicitly calls overriden handler method.
if (Kohana::$errors AND $error = error_get_last() AND in_array($error['type'],
Kohana::$shutdown_errors))
{
// Clean the output buffer
ob_get_level() AND ob_clean();
// Fake an exception for nice debugging
Kohana_Exception::handler(new ErrorException($error['message'], $error['type'], 0, $error['file'], $error['line']));
// Shutdown now to avoid a "death loop"
exit(1);
}
So my question how do I set up everything to have custom error page for Exception and HTTP_Exception?
PS. I can ovveride HTTP_Exception_404 and HTTP_Exception_500 to have my custom error page displayed, but I don't think that's the best option since it could work for these two, but overriding all possible HTTP_Exceptions is not a good way to go.
PS2. Or I can set my custom view in bootstrap.php:
Kohana_Exception::$error_view = 'custom_error.tpl';
Also don't like that solution.
All links to Kohana's documentation in this post are for version 3.3
You won't get what you want by overwriting just one method. Below I explain the methods that you can overwrite in order to achieve what you want. Just make just sure you put the right code in the right method.
Don't try to do everything in one place. While it will be all in one place is will most likely become a mess.
Kohana_Exception::handler()
Kohana_Exception::handler() is for when exceptions reach the exception handler or like you showed, in the shutdown handler. The last chance you have to display a nice error page in production environments. It outputs the result of Kohana_exception::_handler(), which is a Response object, and is therefor not suited to be called inside Request_Client_Internal::execute_response().
For production: Log the original exception. Since this scenario matches the description of HTTP Status Code 500 (Internal Server Error) Kohana_Exception::handler() should display a 500 error page.
During development you probably want to call parent::handler().
Kohana_Exception::_handler()
Kohana_Exception::_handler() return a Response object, so it is suited to be called in Request_Client_External::execute_response(), Kohana_Exception::handler() and View::__toString().
HTTP_Exception::get_response()
HTTP_Exception::get_response() will get called for exceptions extending HTTP_Exception, with the exception of exceptions extending HTTP_Exception_Expected. A few examples of exceptions extending HTTP_Expected_Exception are the 3xx and 401 HTTP_Exceptions.
By default it returns Kohana_Exception::response().
Overwrite it in specific exceptions to return specific responses for said exception.
Overwrite it in HTTP_Exception when you want the replace the default response.
Kohana_Exception::response()
Kohana_Exception::response() is responsible for collecting the data needed to render the Kohana_Exception::$error_view template. An example of output can be seen on the kohana/errors page of the userguide.
Change Kohana_Exception::$error_view when you want a different layout for the same data.
Overwrite Kohana_Exception::response() to replace the entire thing.
PS. Kevin pointed you to the 3.2 documentation. How to do this is very different for 3.2 and 3.3.

Writing functions that deal with exceptions

Building upon a question I already asked regarding exceptions, I fear that I might be writing php functions wrong then, or abusing the use of exceptions. The reason I say this, is because if custom exceptions are to be caught using try/catch blocks then the following function:
public function get_specific_page($page) {
if (!is_array( $this->_page )){
throw new AisisCore_Template_TemplateException( "<div class='error'>Trying to get a property from a non array.</div>" );
}
return $this->_page[$page];
}
Would then be called such as:
try{
get_specific_page($page);
}
catch(Exception $e){
echo $e->getMessage();
}
The problem with this approach is that I have many functions that are written like this, either checking to see if a file exists, throwing an error. Checking to see if a value is set in an array, throwing an error and my issue is that the file which deals with these function calls may become over loaded with try catch.....
So my question is, how would I better write functions like this so that I don't have php files over loaded with try catch statements, yet still be able to have y own custom functions.
Is it as obvious as writing the try catch inside the function it's self?
The reason I ask, if because I am use to working with fameworks and in companies where we write our functions as you see above. How ver I have worked with code bases that have tons of these functions and I dont see half the files that are useing them doing a bunch of try catches...
Update:
I was looking through zend source to better understand exceptions and came across this:
public function setMessage($messageString, $messageKey = null)
{
if ($messageKey === null) {
$keys = array_keys($this->_messageTemplates);
foreach($keys as $key) {
$this->setMessage($messageString, $key);
}
return $this;
}
if (!isset($this->_messageTemplates[$messageKey])) {
require_once 'Zend/Validate/Exception.php';
throw new Zend_Validate_Exception("No message template exists for key '$messageKey'");
}
$this->_messageTemplates[$messageKey] = $messageString;
return $this;
}
You can see how they throw a new exception message near the bottom, this function is not called by doing:
try{}catch(){}
yet when it throws an exception, there is no issue with "uncaught exception with message"
In my opinion, your approach is correct in general. However, a few notes:
You should refrain from using HTML formatting in exception messages. Generally, you don't know how the exception that you throw will be handled. For example, an exception handler could just write the message to a log file (you don't want HTML formatting then), present it to the user in a special error view (in which case the view itself should contain the HTML formatting), or simply ignore it (no need for formatting then, anyway).
Catch only exceptions that you can handle. If you know that your function throws an AisisCore_Template_TemplateException, you should just catch that exception and let all other exceptions bubble up to an exception handler that can handle them. You can use set_exception_handler to define such an exception handler that catches all uncaught exceptions by default (this is probably the case in your example from Zend Framework). Plainly put: Only catch exceptions in places where you know how to handle them.
Only use exceptions as what the name implies: to handle (unexpected) exceptions in your control flow. Using exceptions to control the regular flow of your program is possible, but generally considered bad design (just as a side note, your code samples look alright).
For the sake of completeness, some alternatives to using exceptions:
Use return codes instead of exceptions. This is old-school C-style. The advantage is that you don't need to wrap statements with try/catch-statements. However, you have to check the return values of each procedure, which is easy to forget. When using exceptions on the other hand, you reduce the risk of unexpected errors, since uncaught exceptions produce a fatal error per default.
Use PHP errors. See the trigger_error function for this. Custom errors are however nearly impossible to catch in PHP (except by using set_error_handler, which only works at global level).

When should you use PHP Exceptions?

I've seen lots of tutorials that demo simple try catches with, say, the act of opening a file. But I've never seen a big, "real" example. Can someone provide me with a few cases in which they have or would use exceptions? And is it really necessary to extend the exception class just to throw an exception? And finally, when throwing exceptions, does it cause the script to exit(); ? Or, does it log it and continue on with script execution?
We use exceptions extensively within our projects.
One specific instance is for actions that require the user to be logged in or upon registration. We use Exceptions for flow control on error conditions. If the current user is not logged in we throw an exception. The exception handler then redirects them to the loggin page.
Using our registration action as an example, we extend the Exception like this:
class RegistrationFailed extends Exception {}
Now in our catch statement within the registration code we can test for the RegistrationFailed exception and handle it accordingly. Otherwise, when the exception is not a RegistrationFailed, we allow it to bubble up because we are not interested in it.
try {
// do registration here
}
catch(RegistrationFailed $e) {
// handle the failed registration
}
catch(SomeOtherException $e) {
// handle other errors like this...
}
// All other errors will not be caught and will bubble up
Another example is within our wrapper classes which developers must extended. We use Reflection to ensure the child classes have properly implemented their methods and provided the correct interface. If not we notify the developer of that class via Exceptions letting them know a specific interface or method must be provided by the child class.
Edit:
I can already hear the comments about "You shouldn't use error handling for flow control!" however, for the project discussed above, it was necessary.
In the normal flow of the program a failed registration is expected due to the many validation rules that might fail, like a password that's too short.
However, it's an ajax application, so it's possible that someone might try to access an ajax url manually, when they are not logged in. This is as exception and thus we handle it as such.
Exceptions are meant to handle errors (at least in PHP). Suppose you are in a routine, and an error is occured that you can't handle in the current context.
Example:
<?php
/**
* #throws Exception_NoFile
*/
function read_file($file) {
if(!file_exists($file)) {
throw new Exception_NoFile($file);
}
/* ... nominal case */
}
In this situation you can't continue with the nominal case, becouse there is no file to process. You have to choose:
return with an invalid return value (this is the C practice, e.g: return -1 or using status flags)
throw an exception, and hope, someone will catch it above. If your client code excepts it, no problem, it may try an other path or rethrow an exception. If your client isn't ready to handle those situations where the requested file doesn't exist... your code will fail with an uncached exception, as it would do with a read of a nonexisting file in the other approach.
I feel a lot of people confuse 'failures' and 'exceptions' as the same thing. The word 'error' could refer to either but I use it for failure.
Failure - when the operation doesn't succeed
Exception - when an unexpected or out of the normal flow condition arises
For example, if a robot tries to walk to a destination and misses the mark - that's failure. But if it breaks a leg or the roof falls on it, that's an exception.
If the roof falls, I throw an exception that the roof fell.
If the robot misses the mark, I don't throw an Exception, I return false or return an error message like "Could not reach the destination because the roof fell."
try {
Walk to the cabinet;
}
catch (RoofFell_Exception $e) {
return "Could not reach the destination because the roof fell.";
}
catch (Legbroke_Exception $e) {
return "Could not reach the destination because a leg broke.";
}
if($current_location == 'cabinet') {
return "Destination reached";
}
return false;
Exception handling is tricky. It requires careful consideration of the project at hand and the way errors can be dealt with. You should try to define your Exceptions Guidelines early in your project and adhere to it.
I have written a general Exceptions Guidelines best practices that I have come up with after extensive research of the subject. Most of these guidelines can be used to all projects in any language that supports exceptions. Some of the guidelines will be Java specific. At the end you need to have a robust set of guidelines that can help you handle and deal with exceptions and error conditions.
Here are some points to consider
Don’t expose internal, implementation specific details to your clients
Avoid exposing internal implementation specific exceptions to your clients, especially those contained in a third party library. This is a general object oriented rule of thumb and it’s as valid for your exceptions hierarchy design. You have no control over the third party library which can change its exceptions signatures and break all of your API contracts with your clients. Instead wrap those third party exceptions (such as an SQLException) in your own custom exceptions. This way you’ll have much greater flexibility to change the third party library in the future without breaking your clients’ API contract.
Create your own exceptions hierarchy for complex projects
Generally speaking create your own exceptions hierarchy for more complex modules especially if you are dealing with implementation specific exceptions in third party libraries. Each of your packages/modules could have its own top-level generic exceptions. For Java at least one should be defined that inherits from RuntimeException. Wrap all implementation specific exceptions in your custom exceptions so that your clients should only depend on your custom exceptions and/or generic Java exceptions. This will give you greater flexibility to refactor the implementation specific code later without breaking your API contracts.
If more fine grained error handling is necessary then you can further subclass your custom exceptions to handle specific cases and allow for error recovery. For example if you are connecting to an SQL database you can throw a ConnectionTimeoutException in such a way that if needed the client can retry the connection N times before giving up. This way you can later change your database engine to NoSQL and still allow for reconnects and the client code will stay the same.
Document all exceptions
Carefully document all exceptions your package/module/app throws in the javadoc definition of each public method. Failing to do so will frustrate your API users and cause them to not trust your API docs. You don’t really want your clients to dig in your source just to find out that you are throwing a specific exception, right?
Throw exceptions as early as possible.
Check all inputs to your public API methods and throw an exception as soon as you find inconsistencies between your expected parameters and what has been supplied. The earlier you throw an exception the less will be the chance of data corruption, because bad data won’t make it into the deeper parts of your code. It also gives valuable feedback to your clients in a timely manner instead of deep in your code where something throws an obscure exception with a bad message such as ‘Internal Error’ or NullPointerException.
Log exceptions properly
Follow the guidelines of your logging framework in order to properly log exceptions with their message and stack trace. You don’t want to loose either
You should check out symfony framework - they really use a lot of Exceptions there.
They use Exception for configuration errors, say you forgot to put a file where the controller expects to find it - this will be an Exception, because there isn't anything framework can do it about it.
They use Exception for unknown errors: database failed for some weird reason, there's nothing framework can do about it - so it throws an Exception
And they have different Exception handlers for different environments. When exception occurs in "devel" mode, you get a nice page with stack trace and an explanation, when you are in "production" mode, you are redirect to custom 500 page.
Exceptions are simply a way to move edge cases or errors (which are really just big edge-case events) out of the larger body of code to stop them from making 99% of the basic stream of code cluttered with tons of switches/ifs.
You can think of them as a kind of reverse switch statement, where the events inside the try{} determine which, if any, catch block happens too.
What that means is that you don't ever have to use them if you don't like them. But they can make code easier to read.
A great place to use exception handling is when your program attempts to connect to, or access, I/O (files, databases, networking, devices).
Use exception handling when a block of calling code (function/method) attempts to access a file.
Use exception handling when a block of calling code (function/method) attempts a database connection.
Use exception handling when a block of calling code (function/method) attempts to run a query on a database (any attempt at accessing the database tables/views and such).
You could say the same about a network connection or access.
Memory access requires I/O (that includes storing things in $_SESSION files), but most beginners don't put their entire program within the confines of a try...catch structure. A good example of the use of exceptions and extending the Exception class can be found in Matt Doyle's book Beginning PHP 5.3, ch. 20, p. 652-60.
I might also say that learning to combine the use of exception handling with set_error_handler(), trigger_error(), error_log() inside of the catch block can allow you to preserve custom, developer friendly, error messages you may have been echoing to your output device (browser/stdout) in development. That is, in production, your php.ini will have display_errors off and log_errors will be on. Where you may have echoed something like "Oops, I cannot connect to the accounting database" when a connection to said database failed, simply send that same string of text to error_log() and your personal error messages can still be logged.
Example:
function custom_handler($arg1, $arg2, $arg3, $arg4, $arg5)
{
...
...
error_log(blah, blah, blah)
}
set_error_handler('custom_handler'); <--takes over this duty from PHP
$error = NULL;
try
{
if(!connect_to_mythical_database('accounting'))
{
$error = 'I cannot connect to the accounting database';
throw new Exception(supply-correct-arguments);
}
}
catch (Exception $e)
{
trigger_error(supply-correct-arguments); <-- does what 'custom_handler' instructs.
error_log($error, blah, blah); <---Your friendly message here
header('Location: http://www.myhomepage.com');
exit;
}
Note: Inside of custom_handler(), you can use error_log() to log PHP error messages in a file, email them, or both log and email the standard PHP error messages. Thus, trigger_error() is either controlled by PHP (default) or by your 'custom_handler', which can implement error_log()', all of which can be activated by thecatch` block of your exception handler.

Categories