#1
  1. --
    Devshed Expert (3500 - 3999 posts)

    Join Date
    Jul 2012
    Posts
    3,959
    Rep Power
    1014

    The mystery of errors and exceptions


    Hi,

    since many people seem to struggle a lot with error reporting and exception handling, and since the same nonsense „solutions“ still get copied and pasted around, this is an attempt of clearing things up a bit.



    Premises


    What error reporting is supposed to do:
    • distinguish between end-users and developers
    • provide developers with detailed error reports
    • provide end-users with a short, generic error message and a 5xx status code


    What error reporting is not supposed to do
    • leak critical information (file paths, queries, your database credentials, ...)
    • irritate users with technical bug reports
    • stay silent




    Common mistakes


    Displaying internal errors generated by PHP

    This is probably the most common mistake. Outputting PHP errors makes sense during development, but on the actual website, it’s very dangerous for you and irritating for your users. The PHP error messages are meant for developers, not application users. If they pop up on your website, they help attackers with detailed information while scaring legitimate users.

    Since this often happens due to a misconfiguration, make sure to properly configure PHP as explained below.


    Displaying internal errors from subsystems

    Another common mistake is taking the error messages from, for example, MySQL and dumping them on the screen with a die() or an echo. Check this pattern, which is an all-time favorite of many bullsh*t „tutorials“ and gets copied and pasted around since PHP was invented:

    don’t use
    PHP Code:
    mysql_query(...) or die(mysql_error()); 
    There’s also an object-oriented variant:

    don’t use
    PHP Code:
    try {
        
    $db->query(...);
    } catch (
    PDOException $e) {
        echo 
    'Query failed: ' $e->getMessage();

    What’s wrong with this is that it again displays an internal error message not meant for end-users. The message will contain critical information like the exact query or even your database credentials. But it’s actually even worse than a misconfiguration, because this mistake cannot be fixed globally. A die() is a die(), you cannot turn it off. You have to actually go through your whole code and delete those parts manually.

    So never use echo or die() to display error messages from databases or other systems.



    Proper error reporting


    Configuring PHP

    Start off by opening the php.ini. Note that you cannot do the error configuration within the script, because PHP might fail before the script is even executed.

    The four most important directives are:
    • error_reporting: which errors should be displayed or logged
    • display_errors: whether or not internal error messages should be displayed on the website
    • display_startup_errors: whether or not errors within the PHP system itself should be displayed
    • log_errors: whether or not errors should be written to a log; the log can be specified with error_log

    During development, you’ll probably want to see all error messages in the browser and not log them. Do this by setting error_reporting to -1, display_errors and display_startup_errors to On and log_errors to Off. You can also exclude specific errors using the error constants. Avoid using E_ALL. Despite its name, it doesn’t cover E_STRICT errors prior to PHP 5.4.

    Use during development
    Code:
    error_reporting = -1
    
    display_errors = On
    
    display_startup_errors = On
    
    log_errors = Off
    On the actual website, PHP must not output any internal error messages, so set display_errors and display_startup_errors to Off. If you want to log the errors, set error_reporting to the appropriate level, turn log_errors on and set the error_log if needed.

    Use for production
    Code:
    error_reporting = -1    ; if your code is sloppy, this will quickly fill the error log, so use an appropriate level
    
    display_errors = Off
    
    display_startup_errors = Off
    
    log_errors = On
    Setting up a custom error page

    If you’re using nginx with a current PHP version (at least 5.2.4) over FastCGI, this is easy: enable fastcgi_intercept_errors and define an error_page for 500 errors.

    PHP >= 5.2.4 will automatically generate a 500 code under the following conditions: a fatal error has occured, display_errors is set to Off and no output has been sent yet. All you have to do is catch the 500 code and have nginx handle it.

    Use with nginx + PHP >= 5.2.4
    Code:
    fastcgi_intercept_errors  on;
    
    error_page  500  /error_pages/5xx.html;
    
    location /error_pages {
        internal;    # the error pages should not be publicly accessible
    }
    If you’re using Apache, you need to do some handiwork. Since Apache doesn’t intercept 500 errors issued by PHP, you’ll get a blank page by default. Any custom error page must be sent by PHP itself. However, you cannot do this in the actual script, because several errors like E_PARSE prevent the script from ever being executed (as already mentioned above).

    The workaround for this is to create a separate script with a shutdown handler and prepend it to every script using auto_prepend_file in the php.ini:
    Code:
    auto_prepend_file = 'path/to/fatal_error_handler.php'
    A shutdown handler is executed after the actual script has been run or aborted, so it can be used to catch even severe errors like erroneous syntax. Prepending the helper script makes sure that the shutdown handler is registered before the actual script might crash everything.

    Use with Apache + PHP >= 5.4
    PHP Code:
    <?php

    register_shutdown_function
    ('handle_fatal_errors');

    function 
    handle_fatal_errors() {
        
    // display error message if the response code is 500 (either due to a fatal error or a custom header() call) and display_errors is turned off and nothing has been sent yet
        
    if ( http_response_code() == 500 && !ini_get('display_errors') && !headers_sent() ) {
            
    // flush any buffered content (assuming this is garbage generated before the error occured)
            
    ob_clean();
            
    // send a 500 status code and an error message
            
    echo 'Sorry, an error has occured. The webmaster has been notified and will fix the issue as soon as possible. Please try again later.';
        }
    }
    Use with Apache + PHP < 5.4
    PHP Code:
    <?php

    register_shutdown_function
    ('handle_fatal_errors');

    function 
    handle_fatal_errors() {
        
    $fatal_errors =
            
    E_ERROR E_PARSE E_CORE_ERROR E_COMPILE_ERROR E_USER_ERROR E_RECOVERABLE_ERROR;
        
    $last_error error_get_last();
        
    // display error message if there was a fatal error and display_errors is turned off and nothing has been sent yet
        
    if ( $last_error && ($last_error['type'] & $fatal_errors) && !ini_get('display_errors') && !headers_sent() ) {
            
    // flush any buffered content (assuming this is garbage generated before the error occured)
            
    ob_clean();
            
    // send a 500 status code and an error message (see http://stackoverflow.com/questions/3258634/php-how-to-send-http-response-code)
            
    header('X-PHP-Response-Code: 500'true500);
            echo 
    'Sorry, an error has occured. The webmaster has been notified and will fix the issue as soon as possible. Please try again later.';
        }
    }
    Using custom errors or exceptions

    In case you want to generate a custom error within the script (like when a query fails), always use the trigger_error() function or an exception (see below). This will adhere to the error procedure and not just dump the message on the screen no matter what.

    PHP Code:
    $query mysql_query(...);
    if (!
    $query)
        
    trigger_error('Query failed: ' mysql_error(), E_USER_ERROR); 
    Note that the old MySQL extension is hopelessly outdated and has already been replaced 10 years ago. If possible, switch to one of the new extensions. They no longer require you to manually check the status of each query.



    Exceptions


    If you’re dealing with modern, object-oriented PHP code, you have to consider yet another error mechanism: exceptions. An exception is a special object indicating a certain kind of error.

    Since exceptions are pretty „new“ in the PHP world, they don’t seem to be very well understood. A common misconception is that somehow every piece of code that might throw an exception must be wrapped in a try-catch block. This is not the case.

    Check this piece of code from the PHP manual, which is yet another example of bad ideas being mindlessly copied and pasted through the whole internet:

    don’t use
    PHP Code:
    try {
        
    $db = new PDO($dsn$user$password);
    } catch (
    PDOException $e) {
        echo 
    'Connection failed: ' $e->getMessage();

    This is dangerous, error-prone and completely useless for many reasons:
    • It will simply dump the error message on the screen, completely ignoring the PHP configuration. The error will leak critical information about your database and your queries (see „Common mistakes“).
    • It does what an uncaught exception would do, anyway – except that it cuts off important information like the file name, line, stack trace etc. and turns a smart exception into a dumb die().
    • The code can hardly be reused in a bigger system, because it could stop the whole application at any time. There’s no chance to catch the exception on a higher level. Wasn’t reusability the whole point of object-oriented programming?
    • Doing this procedure for every query clutters up the whole application with useless, repetitious code

    So this is obviously a bad idea. It’s probably just meant to demonstrate how exceptions can be fetched, but many people actually copy and paste the literal code.

    Exceptions are designed to be smart. They do not have to be fetched right away like a return value. Instead, they can „bubble up“ and be caught later – or not at all. An uncaught exception will generate a fatal error and trigger the standard error procedure, which should work fine for most of your exceptions.

    This allows for very sophisticated error handling – but only if used properly:
    • Only catch an exception if you actually want to handle it in a specific way. In case of a database failure, for example, you might want to retry the connection, switch to an alternative connection etc. Otherwise, just let the exception bubble up and catch it later or not at all.
    • Don't repeat yourself. When you have multiple exceptions that should all be handled in the same way, catch them on a higher level.
    • Catch specific exceptions, not the generic Exception class. This class includes all exceptions, so you might unintentionally „swallow“ other important errors.

    Comments on this post

    • MrFujin agrees : nice explanation
    • r3wt agrees : thanks for the practical Nginx Tip.
    The 6 worst sins of securityHow 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".
  2. #2
  3. Lord of the Dance
    Devshed Expert (3500 - 3999 posts)

    Join Date
    Oct 2003
    Posts
    3,706
    Rep Power
    1959
    Great post.

    We can only hope that people start to take care and get/use the necessary time to make things properly.

    PS: where did my reputation comment go? hidden?

    Comments on this post

    • requinix agrees : it's a rare bug. the rep+comment is still there though - check his profile
  4. #3
  5. --
    Devshed Expert (3500 - 3999 posts)

    Join Date
    Jul 2012
    Posts
    3,959
    Rep Power
    1014
    Originally Posted by MrFujin
    We can only hope that people start to take care and get/use the necessary time to make things properly.
    Hopefully. Unfortunately, it's very easy to just copy and paste the bad stuff that's available everywhere, but it's pretty hard to do things right.

    Other languages have one way of indicating errors, PHP has three of them (return values, errors and exceptions). Other languages let you do global error handling by simply wrapping the main script in a try-catch statement, PHP makes you jump through hoops to actually get all errors. Yeah, there's set_error_handler(), but many error will just slip through that error handler -- and you have to reimplement the whole error system.

    I have no idea why people keep saying that PHP is simple.



    Originally Posted by MrFujin
    PS: where did my reputation comment go? hidden?
    I can see it in my profile. Thanks.
    The 6 worst sins of securityHow 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".
  6. #4
  7. Lord of the Dance
    Devshed Expert (3500 - 3999 posts)

    Join Date
    Oct 2003
    Posts
    3,706
    Rep Power
    1959
    Originally Posted by Jacques1
    I have no idea why people keep saying that PHP is simple.
    You more or less just answered this yourself.
    Those people live in the perfect (/flawless) world. Then PHP is simple I guess.

    Comments on this post

    • Jacques1 agrees
  8. #5
  9. Mad Scientist
    Devshed Expert (3500 - 3999 posts)

    Join Date
    Oct 2007
    Location
    North Yorkshire, UK
    Posts
    3,661
    Rep Power
    4124
    Originally Posted by Jacques1
    I have no idea why people keep saying that PHP is simple.
    because those 'people' are the ones copying and pasting or a writing code which 'works' (code which behaves as expected only when used as intended) first time and have no idea about the concepts of Exceptions or what to do (or just don't) if the query did fail on their 1-visitor a day 4 page website on a cheap host

    Comments on this post

    • Jacques1 agrees
    I said I didn't like ORM!!! <?php $this->model->update($this->request->resources[0])->set($this->request->getData())->getData('count'); ?>

    PDO vs mysql_* functions: Find a Migration Guide Here

    [ Xeneco - T'interweb Development ] - [ Are you a Help Vampire? ] - [ Read The manual! ] - [ W3 methods - GET, POST, etc ] - [ Web Design Hell ]
  10. #6
  11. A Change of Season
    Devshed Frequenter (2500 - 2999 posts)

    Join Date
    Mar 2004
    Location
    Next Door
    Posts
    2,687
    Rep Power
    171
    Hi;

    A few things.


    1 - About different php error types:

    Please correct these if wrong. Working on localhost with PHP 5.5.9 I seem to be able to categorise errors and warnings in to 4 main categories.

    1. Parser error: Parser error happens if there is a syntax error in the script. These errors stops execution of the script.
    2. Fatal errors: Php understands the code (unlike Parser error) but the code doesn’t make sense to parser - or the logic is wrong -.
    3. Warnings: Will not stop execution of the script. Usually caused by including a missing file or incorrect number of the function arguments.
    4. Notices: Usually caused by trying to access undefined variables.


    2 - How would you handle "Parser" errors

    I do wonder if it is possible to handle syntax errors with user friendly message.

    3 - Most important: Exceptions!

    There are tones of material on the net about this. I am gonna quote you:"If you’re dealing with modern, object-oriented PHP code, you have to consider yet another error mechanism: exceptions. An exception is a special object indicating a certain kind of error.". Right after that you jump into what not to do. None of these (including your post) explain "what type of errors can be handled with Exceptions. A lot example are database related. Please specifically clarify what types of errors to be handled with Exceptions.

    4 - How to use Exceptions properly?

    You say "Don't use"
    PHP Code:
    try {
        
    $db = new PDO($dsn$user$password);
    } catch (
    PDOException $e) {
        echo 
    'Connection failed: ' $e->getMessage();

    Do you mean DO use
    PHP Code:
    try {
        
    $db = new PDO($dsn$user$password);
    } catch (
    PDOException $e) {
        
    //echo 'Connection failed: ' . $e->getMessage();
    echo "Sorry, an error has occured. The webmaster has been notified and will fix the issue as soon as possible. Please try again later.";

    If no, please show the right solution and if yes, how does admin get notified? Simply an email in the script?



    5 - About Exception getMessage() method

    Why can't I see getMessage in the list of methods when I print_r($e)?
    PHP Code:
    catch (Exception $e)    
        {
            
    print_r($e);
            echo 
    $e->getMessage();
        }
    /*prints
    Exception Object
    (
        [message:protected] => Error Processing Request 1. File does not exist<br />
        [string:Exception:private] => 
        [code:protected] => 1
        [file:protected] => /Applications/XAMPP/xamppfiles/htdocs/oop/index.php
        [line:protected] => 9
        [trace:Exception:private] => Array
            (
                [0] => Array
                    (
                        [file] => /Applications/XAMPP/xamppfiles/htdocs/oop/index.php
                        [line] => 23
                        [function] => check
                        [class] => DB
                        [type] => ->
                        [args] => Array
                            (
                            )

                    )

            )

        [previous:Exception:private] => 
    )
    error happened 
    */ 


    6 - Catching warnings? "F you we don't catch warnings" you might say; Well I wanna

    You probably have answered this above but how can I catch a warning in this code? I understand in production error_reporting = -1 and the error log will be filled with errors. But in case it happens, what would be the proper way to show the message to visitors? Please preview on this code below.
    PHP Code:
    How can I catch warning?
    class 
    file_manager{
        public function 
    __construct(){
            if(!
    file_put_contents(time().".txt",time())){
                throw new 
    Exception("Could not write to file!");
            }
            echo 
    "File written successfully";

        }
    }

        try {
            
    $file = new file_manager();    
        } catch (
    Exception $e) {
            echo 
    $e->getMessage();    
        } 

    7 - Php interpreter vs php parser vs php compiler

    What's the difference? I see a lot of different ambiguous descriptions on the net. Can you clarify please?

    9 - Can you show what happens when the code is being executed?

    Probably with a graph like this


    8 - About php.ini:

    1 - While I have XAMPP up and running, it seem that my machine using /usr/bin/php
    Code:
    which php
    /usr/bin/php
    But if I place phpinfo(); in a script anywhere in /Applications/XAMPP/htdocs/anydirectory here I get Configuration File (php.ini) Path 's value /Applications/XAMPP/xamppfiles/etc . This causes a little bit of confusion since I am not sure which php.ini is in use.

    Probably on the same topic my machine is using /Applications/XAMPP/etc/extra/httpd-vhosts.conf along with /etc/hosts. I wonder why /Applications/XAMPP/etc/hosts and /etc/apache2/extra/httpd-vhosts.conf are both being ignored. You might have an explaination on that too.
    Back to php.ini. You mentioned "Note that you cannot do the error configuration within the script, because PHP might fail before the script is even executed.".
    In php.ini I see these lines. If you look at main index.php file of CodeIgniter you will find these lines of code. Have they selected this approach because they thought developer's might not have access to php.ini or is it simply because they are ignorant? Or any other reasons?

    PHP Code:
    if (defined('ENVIRONMENT'))
    {
        switch (
    ENVIRONMENT)
        {
            case 
    'development':
                
    error_reporting(E_ALL);
                
    ini_set('display_errors'1);
                

            break;
        
            case 
    'testing':
            case 
    'production':
                
    error_reporting(0);
            break;

            default:
                exit(
    'The application environment is not set correctly.');
        }
        
    error_reporting(E_ALL);
        
    ini_set('display_errors'1);    




    Thanks
  12. #7
  13. --
    Devshed Expert (3500 - 3999 posts)

    Join Date
    Jul 2012
    Posts
    3,959
    Rep Power
    1014
    Originally Posted by English Breakfast Tea
    Please correct these if wrong. Working on localhost with PHP 5.5.9 I seem to be able to categorise errors and warnings in to 4 main categories.

    1. Parser error: Parser error happens if there is a syntax error in the script. These errors stops execution of the script.
    2. Fatal errors: Php understands the code (unlike Parser error) but the code doesn’t make sense to parser - or the logic is wrong -.
    3. Warnings: Will not stop execution of the script. Usually caused by including a missing file or incorrect number of the function arguments.
    4. Notices: Usually caused by trying to access undefined variables.
    Pretty much. All in all, there are currently 15 error types. I would categorize them like this:

    • start-up errors which happen before the actual script is executed (this includes parse errors or internal system errors)
    • fatal errors which happen during script execution
    • notice-like errors (this includes notices, warnings, strict-standards errors and deprecation errors)
    • user-level errors which you can trigger yourself with trigger_error()




    Originally Posted by English Breakfast Tea
    I do wonder if it is possible to handle syntax errors with user friendly message.
    You use the auto_prepend_file directive to register an error handler before the actual script is parsed. This will catch parse errors as well (as explained above).

    If your application has a single access script which receives all requests and then includes the appropriate classes etc., you can also set the error handler in this script. This will also catch parse errors from the included scripts.

    But the best solution is to not have syntax errors in a live environment.



    Originally Posted by English Breakfast Tea
    There are tones of material on the net about this. I am gonna quote you:"If you’re dealing with modern, object-oriented PHP code, you have to consider yet another error mechanism: exceptions. An exception is a special object indicating a certain kind of error.". Right after that you jump into what not to do. None of these (including your post) explain "what type of errors can be handled with Exceptions. A lot example are database related. Please specifically clarify what types of errors to be handled with Exceptions.
    Exceptions are simply one way of representing errors. They can be used as an alternative to the classical approach of having special return values (like “false means the function failed”) and generating PHP errors.

    When to use which system is completely up to the programmers. The PHP core mostly uses the classical error system, but some of the newer object-oriented interfaces (like DateTime, PDO or MySQLi) use exceptions instead. Generally speaking: People who write procedural code usually prefer errors, people who write OOP code usually prefer exceptions. But there's no law for this.



    Originally Posted by English Breakfast Tea
    You say "Don't use"

    [catching PDO exceptions and outputting the internal error message]

    Do you mean DO use

    [catching PDO exceptions and outputting a user-friendly message]

    If no, please show the right solution and if yes, how does admin get notified? Simply an email in the script?
    I'm saying that it makes no sense to catch the exception at this point. I mean, do you wanna repeat this try-catch block for every single statement which may throw an exception? That would be insane.

    Simply let the exception alone so that it can be caught by the global error handler. That's where you put the error logic. Write the error message to the log file with error_log(). Sending out an e-mail would also be an option if it's a severe error.

    Don't catch an exception unless you actually wanna do something with it. If you wanna retry the database connection or something like that, it makes sense to catch the exception. Otherwise, leave it alone. The global error handler will take care of it.



    Originally Posted by English Breakfast Tea
    Why can't I see getMessage in the list of methods when I print_r($e)?
    print_r() doesn't show any methods. That's what get_class_methods() is for.



    Originally Posted by English Breakfast Tea
    You probably have answered this above but how can I catch a warning in this code? I understand in production error_reporting = -1 and the error log will be filled with errors. But in case it happens, what would be the proper way to show the message to visitors? Please preview on this code below.
    PHP Code:
    How can I catch warning?
    class 
    file_manager{
        public function 
    __construct(){
            if(!
    file_put_contents(time().".txt",time())){
                throw new 
    Exception("Could not write to file!");
            }
            echo 
    "File written successfully";

        }
    }

        try {
            
    $file = new file_manager();    
        } catch (
    Exception $e) {
            echo 
    $e->getMessage();    
        } 
    Again: Don't catch an exception unless you actually wanna do something with it. If you don't have a solution to this specific problem, leave it alone and let the global error handler take care of it.

    Secondly, don't throw and don't catch instances of Exception. This is the most generic exception class which includes every possible exception. It could be anything from “No file permissions” to “Your CPU has caught fire”. How do you wanna handle all errors with one small code snippet? Always throw and catch specific classes. There are several predefined classes, and you can also define your own.

    In this case, however, I don't understand why you want an exception in the first place. The internal warning gives you a detailed description of what's wrong. Why would you replace that with a vague custom exception?

    To be continued ...
    The 6 worst sins of securityHow 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. --
    Devshed Expert (3500 - 3999 posts)

    Join Date
    Jul 2012
    Posts
    3,959
    Rep Power
    1014
    Part 2:

    Originally Posted by English Breakfast Tea
    7 - Php interpreter vs php parser vs php compiler

    What's the difference? I see a lot of different ambiguous descriptions on the net. Can you clarify please?
    This is way outside the scope of this thread.

    Roughly speaking:

    A parser reads PHP code and turns it into a tree structure for further processing (see abstract syntax tree for concrete examples). This is always the first step, because machines don't understand the raw code. The code is for humans. If you want machines to evaluate it, you first have to convert it into a machine-friendly format.

    An interpreter reads PHP code and immediately executes it. This includes parsing the code. Pure interpreters were only used by very early versions of PHP.

    A compiler reads PHP code and either outputs a native executable or equivalent code of some other language. This again includes parsing. A classical parser was HPHPc from Facebook which turned PHP code into C++ code.

    Current PHP version use a combination of a compiler and an interpreter: They first compile the original code into an intermediate format called “byte code”. And then they run this byte code through an interpreter. This is more efficient than interpreting the raw source code, especially if the code byte is cached.




    Originally Posted by English Breakfast Tea
    9 - Can you show what happens when the code is being executed?

    Probably with a graph like this
    What exactly do you wanna know?



    Originally Posted by English Breakfast Tea
    8 - About php.ini:

    1 - While I have XAMPP up and running, it seem that my machine using /usr/bin/php
    Code:
    which php
    /usr/bin/php
    But if I place phpinfo(); in a script anywhere in /Applications/XAMPP/htdocs/anydirectory here I get Configuration File (php.ini) Path 's value /Applications/XAMPP/xamppfiles/etc . This causes a little bit of confusion since I am not sure which php.ini is in use.
    Where's is the second php.ini? All you've said is that there's one PHP executable in one path and one php.ini in another path. I see no collision there.



    Originally Posted by English Breakfast Tea
    Back to php.ini. You mentioned "Note that you cannot do the error configuration within the script, because PHP might fail before the script is even executed.".
    In php.ini I see these lines. If you look at main index.php file of CodeIgniter you will find these lines of code. Have they selected this approach because they thought developer's might not have access to php.ini or is it simply because they are ignorant? Or any other reasons?
    Because the software is supposed to work even on crappy shared hosts and for very inexperienced developers. A custom php.ini is not always an option then.

    And as you can see, they're changing the settings based on some constant so that people can switch between a live mode and a dev mode.
    The 6 worst sins of securityHow 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".
  16. #9
  17. Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Mar 2014
    Posts
    120
    Rep Power
    1
    thanks for the tidbit on intercepting errors with fastcgi on Nginx. i've witnessed a few sites that did this, but never knew how they accomplished it. one more useful trick to add to the bag. +1 Jacques
  18. #10
  19. A Change of Season
    Devshed Frequenter (2500 - 2999 posts)

    Join Date
    Mar 2004
    Location
    Next Door
    Posts
    2,687
    Rep Power
    171
    Originally Posted by Jacques1
    Exceptions are designed to be smart. They do not have to be fetched right away like a return value.
    There is a sticky called How to program a basic but secure login system using PHP and MySQL.

    The author keeps try catch exception and dies, like this:
    PHP Code:
    try
        {
            
    // This statement opens a connection to your database using the PDO library
            // PDO is designed to provide a flexible interface between PHP and many
            // different types of database servers.  For more information on PDO:
            // http://us2.php.net/manual/en/class.pdo.php
            
    $db = new PDO("mysql:host={$host};dbname={$dbname};charset=utf8"$username$password$options);
        }
        catch(
    PDOException $ex)
        {
            
    // If an error occurs while opening a connection to your database, it will
            // be trapped here.  The script will output an error and stop executing.
            // Note: On a production website, you should not output $ex->getMessage().
            // It may provide an attacker with helpful information about your code
            // (like your database username and password).
            
    die("Failed to connect to the database: " $ex->getMessage());
        } 
    PHP Code:
    try
            {
                
    // These two statements run the query against your database table.
                
    $stmt $db->prepare($query);
                
    $result $stmt->execute($query_params);
            }
            catch(
    PDOException $ex)
            {
                
    // Note: On a production website, you should not output $ex->getMessage().
                // It may provide an attacker with helpful information about your code. 
                
    die("Failed to run query: " $ex->getMessage());
            } 
    PHP Code:
    try
            {
                
    $stmt $db->prepare($query);
                
    $result $stmt->execute($query_params);
            }
            catch(
    PDOException $ex)
            {
                die(
    "Failed to run query: " $ex->getMessage());
            } 
    I might be wrong but isn't it something you say we shouldn't do since visitors do not need to know about the error because 1 - They are not programmers and dont need to know about technical issues and 2 - $ex->getMessage() could reveal confidential information about the app?



    Originally Posted by Jacques1
    Exceptions are simply one way of representing errors. They can be used as an alternative to the classical approach of having special return values (like “false means the function failed”) and generating PHP errors.

    When to use which system is completely up to the programmers. The PHP core mostly uses the classical error system, but some of the newer object-oriented interfaces (like DateTime, PDO or MySQLi) use exceptions instead. Generally speaking: People who write procedural code usually prefer errors, people who write OOP code usually prefer exceptions. But there's no law for this.
    I understand during the development phase - and specially for dealing with built in php classes- Exceptions can be pretty handy. What are some of the benefits of Exceptions vs classical error system. Can you please show with a basic example where classic error handling is not referred ?

    Originally Posted by Jacques1
    Simply let the exception alone so that it can be caught by the global error handler. That's where you put the error logic. Write the error message to the log file with error_log(). Sending out an e-mail would also be an option if it's a severe error. Don't catch an exception unless you actually wanna do something with it. If you wanna retry the database connection or something like that, it makes sense to catch the exception. Otherwise, leave it alone. The global error handler will take care of it.
    I really want to see an example of "doing something with exception" for these below. I want to see how properly to catch an exception, send it to error handler, notify webmaster and show the right message to visitors.
    Originally Posted by Jacques1
    Again: Don't catch an exception unless you actually wanna do something with it. If you don't have a solution to this specific problem
    What is an example of solution to this specific problem, mind an example?
    Originally Posted by Jacques1
    Leave it alone and let the global error handler take care of it.
    Another one that needs an example.
    Originally Posted by Jacques1
    Holy shet! Do I really need to understand this chart?
    Originally Posted by Jacques1
    An interpreter reads PHP code and immediately executes it. This includes parsing the code. Pure interpreters were only used by very early versions of PHP.

    A compiler reads PHP code and either outputs a native executable or equivalent code of some other language. This again includes parsing. A classical parser was HPHPc from Facebook which turned PHP code into C++ code.

    Current PHP version use a combination of a compiler and an interpreter: They first compile the original code into an intermediate format called “byte code”. And then they run this byte code through an interpreter. This is more efficient than interpreting the raw source code, especially if the code byte is cached.
    How do you find time to learn and read all this? Timewise it is impossible to read and learn in this much depth when working full time as well. How much do you read everyday?

    Thanks
  20. #11
  21. --
    Devshed Expert (3500 - 3999 posts)

    Join Date
    Jul 2012
    Posts
    3,959
    Rep Power
    1014
    Originally Posted by English Breakfast Tea
    There is a sticky called How to program a basic but secure login system using PHP and MySQL.

    The author keeps try catch exception and dies, like this:

    [...]

    I might be wrong[/U] but isn't it something you say we shouldn't do since visitors do not need to know about the error because 1 - They are not programmers and dont need to know about technical issues and 2 - $ex->getMessage() could reveal confidential information about the app?
    You're right. This is incorrect error handling. And it doesn't even make sense, because uncaught exceptions automatically output the error message (plus additional info). There's absolutely no point in doing this by hand.

    If I remember correctly, I already pointed this out to E-Oreo, but he wanted to keep it in order to demonstrate the try-catch mechanism or something like that. Anyway, you would never do this in practice, neither in a dev environment nor on a live server.



    Originally Posted by English Breakfast Tea
    I understand during the development phase - and specially for dealing with built in php classes- Exceptions can be pretty handy. What are some of the benefits of Exceptions vs classical error system. Can you please show with a basic example where classic error handling is not referred ?
    Well, the most evident benefit of exceptions is that you don't have to manually check the return value of every function to see if it failed. You simply call the function, and if it fails, it will automatically throw an exception. You don't have to do anything.

    This generally makes the code much, much shorter and cleaner. For example, the old MySQL extension forced you to do a manual error check after every single action:

    PHP Code:
    <?php

    $database 
    mysql_connect(...);

    // Did the database selection fail? Then log the MySQL error message.
    if (mysql_select_db(...) === false)
    {
        
    trigger_error(mysql_error(), E_USER_ERROR);
    }

    // Did the query fail? Then log the MySQL error message.
    $some_query mysql_query(...);
    if (
    $some_query === false)
    {
        
    trigger_error(mysql_error(), E_USER_ERROR);
    }

    // Did the query fail? Then log the MySQL error message.
    $some_other_query mysql_query(...);
    if (
    $some_other_query === false)
    {
        
    trigger_error(mysql_error(), E_USER_ERROR);
    }

    // and so on
    This is a mess.

    If you use PDO with exceptions instead, you don't have to do any of this. You only deal with the errors if you want to. Otherwise, you simply let the exceptions do their work.

    PHP Code:
    <?php

    // no error check required; if something goes wrong, we'll get an exception
    $database = new PDO(...);

    // no error check required
    $some_query $database->query(...);

    // no error check required
    $some_other_query $database->query(...);

    // and so on
    Another benefit of exceptions is that it's very easy to delegate error handling.

    Let's say you have a very complex user authentication method which calls other methods which in turn call other methods etc. Each of those methods may fail, and you wanna catch all errors in the main method in order to display a message like “Sorry, the login failed due to technical problems”. If you use the classical system, you have to manually pass every error all the way up to the main method. With exceptions, you simply wrap the main method in a try-catch block.

    In short, exceptions take care of all the standard error handling so you don't have to. You only jump in if you want to do something special (like the login error message).



    Originally Posted by English Breakfast Tea
    I really want to see an example of "doing something with exception" for these below. I want to see how properly to catch an exception, send it to error handler, notify webmaster and show the right message to visitors.
    You do not catch the exception if you want the error handler to take care of it. That's the point. Uncaught exceptions trigger a fatal error which is then automatically passed to the error handler.

    The first post shows an example error handler which logs the error, displays a user-friendly message and sets a 500 status code. If you wanna send an e-mail, you simply add that. Be careful with e-mails, though. You don't wanna end up with hundreds of notifications about some harmless warning.



    Originally Posted by English Breakfast Tea
    What is an example of solution to this specific problem, mind an example?
    Well, a trivial example would be to retry the database connection if it fails:

    PHP Code:
    $database null;
    $attempts 0;
    do
    {
        try
        {
            
    $database = new PDO('mysql:host=localhost;dbname=YOUR_DB;charset=utf8''YOUR_USER''YOUR_PASSWORD'$database_options);
        }
        catch (
    PDOException $db_exception)
        {
            
    // give up after the third attempt and rethrow the exception
            
    if ($attempts >= 2)
            {
                throw 
    $db_exception;
            }
            else
            {
                
    sleep(1);
            }
        }
        
    $attempts++;
    }
    while (
    $database === null); 


    Originally Posted by English Breakfast Tea
    Another one that needs an example.
    An example for not touching an exception? Well, that simply means doing ... nothing.



    Originally Posted by English Breakfast Tea
    Holy shet! Do I really need to understand this chart?
    No. You wanted to know what a parser does. That graph gives an impression of it.



    Originally Posted by English Breakfast Tea
    How do you find time to learn and read all this? Timewise it is impossible to read and learn in this much depth when working full time as well. How much do you read everyday?
    Not much. I look up specific questions in the manuals, the source code and forums like stackoverflow, then I try things out, do some more reading, try things out etc.
    Last edited by Jacques1; April 3rd, 2014 at 12:05 AM.
    The 6 worst sins of securityHow 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