SitePoint Sponsor

User Tag List

Results 1 to 10 of 10
  1. #1
    SitePoint Evangelist
    Join Date
    May 2006
    Posts
    436
    Mentioned
    2 Post(s)
    Tagged
    0 Thread(s)

    When to use exception handling for website

    Hi,

    I've been reading about exception handling in PHP. The logic of it looks very simple yet I'm confused as to when/how to use it in a website context. From what I can see the advantages are:

    • Throwing multiple exceptions results in more concise code compared to loads of if/elses
    • A thrown exception can be caught outside of the function that threw it
    • You can throw multiple exceptions and only need to catch it once (though you don't have to)
    • It makes use of internal PHP error reporting functionality since you can set error codes and messages and get file, line and trace
    • You can extend the Exception class


    However, it seems to be there is little need for this in a website. I can see in a standard desktop application that is running constantly exceptions need to be handled and dealt with. Let's say I connect to a database and program it so separate exceptions are thrown for 1. Can't connect, 2. Can't set charset, 3. Can't select database

    If any of these exceptions occur, the website is (usually) useless anyway so why not just do some error logging then and exit() or die()?

    A few further questions:

    • In a website, when should it be used? Surely it is not meant for validation. For example, if I am expecting a page number as a GET var, aren't I better off casting it as an int and then checking it is not negative?
    • If the script cannot continue due to a certain exception (e.g. database error as above), should you leave the exception uncaught so it stops the script? (And perform any error logging via set_exception_handler)
    • Is there ever a need to use exception handling with set_error_handler?


    Can someone please help clarify this? Thanks.

  2. #2
    SitePoint Enthusiast Strider64's Avatar
    Join Date
    Aug 2012
    Posts
    37
    Mentioned
    1 Post(s)
    Tagged
    0 Thread(s)
    In my opinion exceptions are not useless, the following doesn't crash the website:

    PHP Code:
    // Fetch the three most recent pages:
    try {
        
        
    $query 'Select id, title, content, DATE_FORMAT(dateUpdated, "%e %M %Y") as dateUpdated FROM pages ORDER BY dateAdded DESC LIMIT 3';
        
    $result $pdo->query($query);
        
        
    // Check that rows were returned:
        
    if ($result && $result->rowCount() > 0) {
            
            
    // Set the fetch mode:
            
    $result->setFetchMode(PDO::FETCH_CLASS'Page');
            
            
    // Records will be fetched in the view:
            
    include('views/index.html');
            
        } else { 
    // Problem!
            
    throw new Exception('No content is available to be viewed at this time');
        }
        
    } catch(
    Exception $e) { // Catch generic exceptions
        
    include('views/error.html');

    PHP Code:
    <!-- # error.html  -->
    <section class="fullWidth">
        <article>
             <h1>An Error Occurred!</h1>
              <p>The content is not viewable because of an error occurred. We apologize for any inconvenience. The system administrator has been notified and will correct the problem as soon as possible</p>
            <p>Details (not for public consumption): <span class="error"><?php echo $e->getMessage(); ?></span></p>
        </article>
    </section>

  3. #3
    SitePoint Evangelist
    Join Date
    May 2006
    Posts
    436
    Mentioned
    2 Post(s)
    Tagged
    0 Thread(s)
    Yes, but why not just go:

    PHP Code:
    // Fetch the three most recent pages:

    $query 'Select id, title, content, DATE_FORMAT(dateUpdated, "%e %M %Y") as dateUpdated FROM pages ORDER BY dateAdded DESC LIMIT 3';
    $result $pdo->query($query);
        
    // Check that rows were returned:
    if ($result && $result->rowCount() > 0) {
            
        
    // Set the fetch mode:
        
    $result->setFetchMode(PDO::FETCH_CLASS'Page');
            
        
    // Records will be fetched in the view:
        
    include('views/index.html');
            
    } else { 
    // Problem!
        
    include('views/error.html');


  4. #4
    SitePoint Enthusiast Strider64's Avatar
    Join Date
    Aug 2012
    Posts
    37
    Mentioned
    1 Post(s)
    Tagged
    0 Thread(s)
    Off the top of my head that you could send (email) the error to the administrator from the exception or an error log, where unless notified by someone or is monitor daily wouldn't know about it. On a small site probably wouldn't be worth it, but on a large site it probably would.

  5. #5
    Community Advisor bronze trophy
    fretburner's Avatar
    Join Date
    Apr 2013
    Location
    Brazil
    Posts
    1,395
    Mentioned
    45 Post(s)
    Tagged
    12 Thread(s)
    set_error_handler() is often used in frameworks to turn php errors into exceptions.

    Exceptions allow you deal with what might otherwise be unrecoverable errors. If a database query fails because of a duplicate id for example, you don't want your end users seeing the error (plus, error messages can often expose details about your app that might be useful to someone trying to hack it) - instead, you can catch the exception, log it, and display a more friendly message and allow the user to take a different course of action.

    One good benefit, in my eyes, is that it allows you to deal with the error anywhere in your calling code, not just in the code that directly calls the method/function that throws the exception - the exception will continue up the chain, until it's caught (or not, as the case may be). This gives you more control about where you choose to put your exception handling code - you don't have to manually pass errors back up the stack.

  6. #6
    SitePoint Evangelist
    Join Date
    May 2006
    Posts
    436
    Mentioned
    2 Post(s)
    Tagged
    0 Thread(s)
    Thanks, I think I'm getting it now. Is this a good case for exception handling?

    1. If can't connect to database, throw exception
    2. If can't select database, throw exception
    3. If can't set charset, throw exception

    Try all three and perform only a single catch. Given that I regard all three are enough to kill the script I simply log the error message, code, line number, etc to a file and display a “The database is currently down, please come back later” type message.

    My second example, is not one that kills the script. I am trying to write to a file that should already exist.

    1. If the file does not exist, throw exception
    2. If the file is not writable, throw exception

    Again, I only need to catch it once so the code is tidier than if/else. In each case, I can display an error message and insert it into an unwritable database and carry on as usual.

    Are these both good use cases?

    So from what I can see so far exceptions are good because:

    1. You can add lots of exceptions in your code and only catch once
    2. You can catch anytime between it getting thrown and the end of the script
    3. The Exception class allows you to create custom error codes/message and get the trace/file/line
    4. You can extend the Exception class for more customised error reporting

    And it shouldn't be used for general validation (form validation, numbers being out of range, etc).

    Finally, is set_error_handler() a good idea? Seem a bit lazy in a global kind of way.

    I guess also, if you have a bootstrap there might be loads of things that could generate an error that warrants killing the script and you could do it all in a single try/catch.

    Thanks.

  7. #7
    Community Advisor bronze trophy
    fretburner's Avatar
    Join Date
    Apr 2013
    Location
    Brazil
    Posts
    1,395
    Mentioned
    45 Post(s)
    Tagged
    12 Thread(s)
    Yeah I think I'd agree with your use of exceptions in those scenarios.

    Quote Originally Posted by DrQuincy View Post
    And it shouldn't be used for general validation (form validation, numbers being out of range, etc).
    I think it depends on the context. If you're calling a validate() method on an object, then you could just return true or false for example, but if you're calling a save() or update() method on your object, then you'd probably want to throw an exception if the data is not valid.

    Quote Originally Posted by DrQuincy View Post
    Finally, is set_error_handler() a good idea? Seem a bit lazy in a global kind of way.
    There is always the risk that your code might cause php to throw an unexpected error which would kill your script and won't look very professional to the end user (not to mention it might expose information that could compromise your system).

    By setting an error handler you can catch these errors and do something about them. It's quite common practice to use this method to convert PHP errors into exceptions which can then be caught locally if you want, but you can also use set_exception_handler to set a global handler to catch any exceptions that you hadn't planned for.

  8. #8
    SitePoint Evangelist
    Join Date
    May 2006
    Posts
    436
    Mentioned
    2 Post(s)
    Tagged
    0 Thread(s)
    Thanks for that.

    This may be a stupid question but if you have something like:

    PHP Code:
    function foo() {

        throw new 
    Exception("Whatever");

        echo 
    "End of foo function";

    }

    try {

        
    foo();

    }
    catch (
    Exception $e) {

        
    // Return back here?


    Is there any way to return back to where the exception was thrown and get End of foo function to echo?

  9. #9
    Community Advisor bronze trophy
    fretburner's Avatar
    Join Date
    Apr 2013
    Location
    Brazil
    Posts
    1,395
    Mentioned
    45 Post(s)
    Tagged
    12 Thread(s)
    Not as far as I know. If foo should still return an output or do some work even in the event of an error that occurs in part of foo's code, then I think you don't really want to be throwing an exception in this case. If the error occurs in a sub-function called from foo, then you could just move your try/catch block inside foo.

  10. #10
    SitePoint Evangelist
    Join Date
    May 2006
    Posts
    436
    Mentioned
    2 Post(s)
    Tagged
    0 Thread(s)
    Great, thanks!


Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •