#1
  1. No Profile Picture
    Contributing User
    Devshed Loyal (3000 - 3499 posts)

    Join Date
    Dec 2004
    Posts
    3,027
    Rep Power
    377

    Exception questions


    I have never really "got" the exceptions but I am trying to learn them Now..

    I am querying a webservice which returns an exception called "ErrorException" when trying to use its login method.. so am i "correct" in using this approach:

    PHP Code:
      try {
           
    $service->login($user_info)
     } catch (
    ErrorException $e) {
       die(
    "Connection error: ".$e->getMessage());


    [/php]
  2. #2
  3. --
    Devshed Expert (3500 - 3999 posts)

    Join Date
    Jul 2012
    Posts
    3,959
    Rep Power
    1014
    Hi,

    we had a similary discussion just yesterday.

    No, it's not correct. Internal error messages are meant for the developers, not the end users. Your users don't need to see your internal bug reports -- in fact, they must not see them, because this could give them critical information and allow them to run specific attacks on your website.

    So this whole die($error->getMessage()) is generally nonsense -- I wonder why it's so popular.

    When you only display the message, you also lose important info like where the exception occured and which function calls lead to it.

    The question is: Why do you even want to catch the exception at that point? Just to write "Connection error:" in front of it? That's kind of pointless.

    Only catch an exception if you actually wanna do something with it -- like retrying the action, using a fallback route etc. Otherwise, just let it "bubble up". On the top level (the PHP script called by your webserver), catch all exceptions, write the important data (message, stack trace etc.) into a log file, send a 500 status code and display some generic error message like "An internal error has occured. Our staff is working hard on fixing it. We are so sorry..." yada yada yada.
    The 6 worst sins of security ē How to (properly) access a MySQL database with PHP

    Why canít I use certain words like "drop" as part of my Security Question answers?
    There are certain words used by hackers to try to gain access to systems and manipulate data; therefore, the following words are restricted: "select," "delete," "update," "insert," "drop" and "null".
  4. #3
  5. Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Aug 2012
    Location
    Burb of Detroit, Michigan
    Posts
    92
    Rep Power
    78
    Since we're on the topic of the die statement, I just wanted to know anyone's thoughts on the following:

    PHP Code:
    try {
      
    $conn = new PDO($dsn$username$password$options );
      
    $conn->setAttributePDO::ATTR_ERRMODEPDO::ERRMODE_EXCEPTION );
    } catch ( 
    PDOException $e ) {
      echo 
    "Connection failed: " $e->getMessage();

    I seen this from a book that I'm currently reading "Beginning PHP 5.3" and no that isn't a typo for echo is written instead of die. I'm suspecting this isn't as bad as using die, my reasoning (which I'm probably wrong) is the echo doesn't stop the script like die does? Though even then I don't see the purpose of the displaying it, for if it doesn't work it doesn't work.
  6. #4
  7. No Profile Picture
    Contributing User
    Devshed Loyal (3000 - 3499 posts)

    Join Date
    Dec 2004
    Posts
    3,027
    Rep Power
    377
    Jacques: funnily enough i have seen that topic/discussion.

    Apologies if i wasnt clear, the main "thing" i wanted to emphasise was the:

    catch (ErrorException $e)

    part.. i.e. i often get confused what should be put in here so if a webservice returns ErrorException should i put that into the ( ) ..

    Also you are right, i am NOT going to display anything to user.. If an error occured, i will "log" it..
  8. #5
  9. --
    Devshed Expert (3500 - 3999 posts)

    Join Date
    Jul 2012
    Posts
    3,959
    Rep Power
    1014
    Originally Posted by paulh1983
    part.. i.e. i often get confused what should be put in here so if a webservice returns ErrorException should i put that into the ( ) ..
    Yes, you should always catch the specific exception you expect from that bit of code. You can also catch different exceptions in different catch blocks.

    But like I said: There's no point in catching an exception if there's nothing you wanna do with it. Logging is done on the top level. It would be insane to repeat the same logging code thousand times for every piece of that that might throw an exception.

    ---------------

    Originally Posted by Strider64
    I'm suspecting this isn't as bad as using die, my reasoning (which I'm probably wrong) is the echo doesn't stop the script like die does?
    It's true that it doesn't stop the script, and that makes it even worse. The script will keep on running until it crashes at the next query with some weird error message talking about a "non-object".

    The problem is that many PHP programmers -- obviously even the ones who write books -- aren't familiar with exceptions at all. Exceptions are pretty "new" in PHP, they were only added in 2004. I have the feeling that people somehow try to do the same (bad) things with exceptions like they did with the old error system they're more familiar with.

    This ... die($error->getMessage()) reminds me of the equally bad ... or die(show_the_error_message()) often seen in old code.
    The 6 worst sins of security ē How to (properly) access a MySQL database with PHP

    Why canít I use certain words like "drop" as part of my Security Question answers?
    There are certain words used by hackers to try to gain access to systems and manipulate data; therefore, the following words are restricted: "select," "delete," "update," "insert," "drop" and "null".
  10. #6
  11. No Profile Picture
    Contributing User
    Devshed Expert (3500 - 3999 posts)

    Join Date
    Jul 2003
    Posts
    3,601
    Rep Power
    595
    Just to continue the useful/uselessness discussion from yesterday. Perhaps, I should have done this to make it clear what the objective was.
    PHP Code:
     try {
           
    $service->login($user_info)
     } catch (
    ErrorException $e) {
       if (
    $debug) {
          die(
    "Connection error: ".$e->getMessage());
       }

    There are 10 kinds of people in the world. Those that understand binary and those that don't.
  12. #7
  13. --
    Devshed Expert (3500 - 3999 posts)

    Join Date
    Jul 2012
    Posts
    3,959
    Rep Power
    1014
    Originally Posted by gw1500se
    Just to continue the useful/uselessness discussion from yesterday. Perhaps, I should have done this to make it clear what the objective was.
    OK, now it's no longer dangerous, but it still makes no sense.

    I mean, do you want to repeat this try-catch block on every single line of your code? Because I'm pretty sure you wanna track all exceptions and not just this particular one (if not, what happens with the others?).

    If you want to specify a global exception handler, make a global try-catch block wrapping all code as explained above:
    PHP Code:
    <?php

    try {
        require 
    'foo';
        require 
    'bar';
        
        ...
        
    some_function();
        
    another_function();
        ...

    } catch (
    Exception $error) {
        
    // if in debug mode, display the message, the stack trace, ...
    }
    You can do the same thing more elegantly with set_exception_handler. Also have a look at set_error_handler, because this will also fetch the old errors.

    Comments on this post

    • gw1500se agrees : I don't want to hijack this thread. I just group all my PDO calls in a single block. It is easier and faster than going back to my logs each time I run. Not looking for elegant, just quick and dirty..
    Last edited by Jacques1; March 8th, 2013 at 09:06 AM.
    The 6 worst sins of security ē How to (properly) access a MySQL database with PHP

    Why canít I use certain words like "drop" as part of my Security Question answers?
    There are certain words used by hackers to try to gain access to systems and manipulate data; therefore, the following words are restricted: "select," "delete," "update," "insert," "drop" and "null".
  14. #8
  15. No Profile Picture
    Contributing User
    Devshed Loyal (3000 - 3499 posts)

    Join Date
    Dec 2004
    Posts
    3,027
    Rep Power
    377
    jacques.. .can you give me an example of a top level exception handler thing you are on about? because I *see* what you are trying to say.. instead of repeating.. just have it once and that makes lot of sense.. would i do: (from googling)

    PHP Code:

    set_exception_handler
    ('myException');

    login..

    if (!
    login) throw new Exception('Uncaught Exception occurred'); 
    or multiple try and one catch :s
  16. #9
  17. --
    Devshed Expert (3500 - 3999 posts)

    Join Date
    Jul 2012
    Posts
    3,959
    Rep Power
    1014
    When you've set the exception handler, it will catch all previously uncaught exception, so you don't need any other try-catch blocks -- unless, of course, you want to handle a specific exception differently.

    PHP Code:
    <?php

    function handle_exception($error) {
        
    header('HTTP/1.1 500 Internal Server Error');
        echo 
    'There was a technical problem. Please try again in 5 minutes.';
        
    // an exception consists of much more than the message, so make sure you also log the other data
        
    error_log($error->getMessage());
    }
    set_exception_handler('handle_exception');

    // test it
    throw new Exception('Oops!');
    Unfortunately, PHP uses three different ways of indicating bugs: return values, errors and exceptions (exceptions are also errors). So you're probably better off using set_error_handler() to catch all errors (including exceptions).

    Note, however, that this completely overrides the default behaviour for errors, so you have to call die() manually to get back the original behaviour. A custom error also can't catch all errors, so you still need to turn display_errors off in your php.ini to prevent the leaking of error messages.

    And the return values of course require extra handiwork.

    Yeah, PHP is a mess.
    The 6 worst sins of security ē How to (properly) access a MySQL database with PHP

    Why canít I use certain words like "drop" as part of my Security Question answers?
    There are certain words used by hackers to try to gain access to systems and manipulate data; therefore, the following words are restricted: "select," "delete," "update," "insert," "drop" and "null".
  18. #10
  19. No Profile Picture
    Lost in code
    Devshed Supreme Being (6500+ posts)

    Join Date
    Dec 2004
    Posts
    8,316
    Rep Power
    7171
    Apologies if i wasnt clear, the main "thing" i wanted to emphasise was the:

    catch (ErrorException $e)

    part.. i.e. i often get confused what should be put in here so if a webservice returns ErrorException should i put that into the ( ) ..
    The first part (ErrorException) is the name of a PHP class. Exceptions are objects, and as such, they have a class type. $e is just the name of a variable to assign the exception to; you can arbitrarily define this.

    The exception will only be caught by that catch block if the type of the exception object is an 'instanceof' of the class defined in the catch block.

    For example, catch(Exception $ex) will catch all exceptions, because all exception classes extend the Exception class.

    catch(ErrorException $ex) will only catch exceptions of the type ErrorException or subclasses of ErrorException. It would not catch a PDOException for example.

    When you throw an exception you are throwing an object. Usually this is reduced to: throw new ErrorException();

    But you could just as easily do:
    PHP Code:
    $ex = new ErrorException;
    throw 
    $ex

    So this whole die($error->getMessage()) is generally nonsense -- I wonder why it's so popular.
    It's popular because when you're writing a tutorial or documentation you want to get rid of as much irrelevant code as possible to avoid using more of the readers' time than necessary. If I'm writing documentation for a webservice with a login method that throws an ErrorException method, it's not relevant to the login() method how the end-user's application handles errors at a global level. Plus, there are dozens of ways of handling errors, and as the documentation writer I have no idea which method a person may be using. Even if I do give an example of global error handling in my documentation code samples, it's going to be useless noise to 90% of the readers.

    So you're probably better off using set_error_handler() to catch all errors (including exceptions).
    Alternatively, you can use an error handler to convert normal errors into exceptions.
    Last edited by E-Oreo; March 8th, 2013 at 10:53 PM.
    PHP FAQ

    Originally Posted by Spad
    Ah USB, the only rectangular connector where you have to make 3 attempts before you get it the right way around
  20. #11
  21. --
    Devshed Expert (3500 - 3999 posts)

    Join Date
    Jul 2012
    Posts
    3,959
    Rep Power
    1014
    Originally Posted by E-Oreo
    It's popular because when you're writing a tutorial or documentation you want to get rid of as much irrelevant code as possible to avoid using more of the readers' time than necessary. If I'm writing documentation for a webservice with a login method that throws an ErrorException method, it's not relevant to the login() method how the end-user's application handles errors at a global level. Plus, there are dozens of ways of handling errors, and as the documentation writer I have no idea which method a person may be using. Even if I do give an example of global error handling in my documentation code samples, it's going to be useless noise to 90% of the readers.
    Yes, that's why the tutorials writers shouldn't catch the exception at all. It's totally useless in this context and gives people the false impression that somehow every new PDO must be wrapped in a try-catch block and that error handling consists of echoing the internal error message on the website (which exceptions do by default, anyway).

    And to be honest: I don't think all those tutorial writers have put as many thoughts into this as you do. They just copy and paste their stuff from someone who has copied and pasted their stuff from someone who has copied and pasted their stuff from someone ... And nobody ever thinks it through.

    It's the same reason why people use
    PHP Code:
    mysql_query(...) or die(mysql_error()); 
    By the way, the intelligent tutorials actually do get it right:

    PHP Code:
    <?php
    try {
        
    //connect as appropriate as above
        
    $db->query('hi'); //invalid query!
    } catch(PDOException $ex) {
        echo 
    "An Error occured!"//user friendly message
        
    some_logging_function($ex->getMessage());
    }
    NOTE: you do not have to handle with try catch right away! you can catch it anytime appropriate. it may make more sense to catch it at a higher level like outside the function that calls the PDO stuff:

    [...]

    or you may not want to handle the exception with try/catch at all, and have it work much like or die(); does. You can hide the dangerous error messages in production by turning display_errors off and just reading your error log.
    Doesn't that wrap it up pretty well?
    The 6 worst sins of security ē How to (properly) access a MySQL database with PHP

    Why canít I use certain words like "drop" as part of my Security Question answers?
    There are certain words used by hackers to try to gain access to systems and manipulate data; therefore, the following words are restricted: "select," "delete," "update," "insert," "drop" and "null".

IMN logo majestic logo threadwatch logo seochat tools logo