Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

I've been using Codeigniter a lot recently, but one thing that gets on my nerves is handling errors and displaying them to the user. I've never been good at handling errors without it getting messy. My main concern is when returning errors to the user.

Is it good practice to use exceptions and throw/catch exceptions rather than returning 0 or 1 from functions and then using if/else to handle the errors. Thus, making it easier to inform the user about the issue.

I tend to go away from exceptions. My Java tutor at university some years ago told me "exceptions shouldn't be used in production code it's more for debugging". I get the feeling he was lying.

But, an example, I have code that adds a user to a database. During the process more than 1 thing could go wrong, such as a database issue, a duplicate entry, a server issue, etc. When an issue happens during registration the user needs to know about it.

What's the best way to handle errors in PHP, keeping in mind that I'm using an MVC framework.

share|improve this question

4 Answers 4

Is it good practice to use exceptions and throw/catch exceptions rather than returning 0 or 1 from functions and then using if/else to handle the errors. Thus, making it easier to inform the user about the issue.

No, no, no!

Don't mix exceptions and errors. Exceptions are, well, exceptional. Errors are not. When you ask a user to enter a quantity of a product, and the user enters "hello", it's an error. It's not an exception: there is nothing exceptional in seeing an invalid input from the user. Why can't you use exceptions in non-exceptional cases, like when validating input? Other people explained it already, and shown a valid alternative for input validation.

This also means that the user don't care about your exceptions, and showing the exceptions is both unfriendly and dangerous. For example, an exception during an execution of an SQL query often reveals the query itself. Are you sure you want to take a risk to show such message to everyone?

more than 1 thing could go wrong, such as a database issue, a duplicate entry, a server issue, etc. When an issue happens during registration the user needs to know about it.

Wrong. As a user, I don't need to know your database issues, duplicate entries, etc. I really don't care about your problems. What I do need to know is that I entered a username which already exist. As already said, a wrong input from me must trigger an error, not an exception.

How to output those errors? It depends on the context. For an already used username, I would like to see a small red flag appearing near the username, before even submitting the form, saying that the username is already used. With no JavaScript, the same flag must appear after submission.

An example of an AJAX-enabled error

For other errors, you would show a full page with an error, or choose another way to inform the user that something went wrong (for example a message which will appear, then fade away at the top of the page). The question is then related more to user experience than to programming.

From programmers point of view, depending of the type of the error, you will propagate it in different ways. For example, in a case of a username already taken, an AJAX request to http://example.com/?ajax=1&user-exists=John will return a JSON object indicating:

  • That the user already exists,
  • The error message to show to the user.

The second point is important: you want to be sure that the same message appear both when submitting the form with JavaScript disabled and typing a duplicate username with JavaScript enabled. You don't want to duplicate the text of the error message in server-side source code and in JavaScript!

This is actually the technique used by Stack Exhange websites. For example if I try to upvote my own answer, the AJAX response contains the error to display:

{"Success":false,"Warning":false,"NewScore":0,"Message":"You can't vote for your own post.",
"Refresh":false}

You can also choose another approach, and preset the errors in the HTML page before the form is filled. Pros: you don't have to send the error message in AJAX response. Cons: what about accessibility? Try to browse the page without CSS, and you'll see all the possible errors appear.

share|improve this answer
    
I appreciate the response. This is exactly what I am struggling with. Do you have any resources on reporting errors, especially in terms of user experience? –  James Jeffery Feb 4 '12 at 21:16
    
Well, like I said, it really depends on the error, and the reporting of errors to the user is strongly linked to the user interface. I also highlighted two main ways to report errors: tight integration (an AJAX-enabled red flag near the input with a wrong value) and full-page errors, much less friendly, used for more severe cases. Doesn't this answer your question? –  MainMa Feb 4 '12 at 21:20
2  
+1 for it being more a user experience issue and not a technical one –  cspray Feb 4 '12 at 22:05
2  
Bullshit, MainMa. Just bullshit. Errorcodes are so 80s and 90s. Exceptions are a much more clean way to handle special circumstances like wrong input (ValidationException for example). You're not forced to display every exception to the user. I've seen better answers of yours. –  Falcon Feb 4 '12 at 22:09
2  
And just in case you didn't know it: You can control which exceptions you want to present to the user and which you don't want presented. So that's not really an argument at all. –  Falcon Feb 4 '12 at 22:22

Is it good practice to use exceptions and throw/catch exceptions rather than returning 0 or 1 from functions and then using if/else to handle the errors. Thus, making it easier to inform the user about the issue.

Yes, yes, yes!

If you want to have clean code, you should almost exclusively use exceptions and don't bother using error codes. Error codes are meaningless. They are almost always tied to some numerical constant that does not reveil much information. It can make your code unreadable and they'll make it hard to propagate data alongside the error.

Exceptions, however, are classes and can contain any information you like. So the user entered a wrong input, like 'abc' for a number field. With an error code you wouldn't be able to propagate this information to the handler of the error without a lot of bubbling. Something that exceptions provide for free. Also, exceptions allow you to have meaningful return values in functions and methods while still having a way to fail elegantly. Even better, Exceptions are propagated right to the place where you want to handle them! Imagine the amount of spaghetti code you'll need to propagate an error code with meaningful data to a handler one or two layers above.

Also, exceptions express so much more semantically than error codes do. Errorcodes lead to spaghetti code where exception handling leads to clean code.

Moreover, it's easy to forget to check status codes. In languages like Java you're forced to handle exceptions (something that for example C# misses).

What's the best way to handle errors in PHP, keeping in mind that I'm using an MVC framework.

Use exceptions and handle them in your controllers.

share|improve this answer
    
I very much agree with you!! Altough exceptions are not as enforced n PHP as in other languages, is good to know that many people are incorprating them... –  David Conde Feb 5 '12 at 3:44
4  
I agree that in most cases error codes are fairly meaningless. However, throwing exceptions willy nilly is extremely bad! Exceptions should be reserved for exceptional circumstances only. Exceptions cause unpredictable program flow, can make code hard to follow (and therefore maintain), and in PHP they carry a rather significant performance penalty compared to IF/THEN/ELSE. I tend to prefer methods to return true on success, false on failure, and only throw an exception of something goes egregiously wrong. –  GordonM Feb 5 '12 at 10:46

Consider this handy little class:

class FunkyFile {               

    private $path;
    private $contents = null;

    public function __construct($path) { 
        $this->setPath($path); 
    }

    private function setPath($path) {
        if( !is_file($path) || !is_readable($path) ) 
            throw new \InvalidArgumentException("Hm, that's not a valid file!");

        $this->path = realpath($path);
        return $this; 
    }

    public function getContents() {
        if( is_null($this->contents) ) {
            $this->contents = @file_get_contents( $this->path );
            if($this->contents === false) 
                throw new \Exception("Hm, I can't read the file, for some reason!");                                 
        }

        return $this->contents;            
    }

}

That's a perfectly fine use of exceptions. From FunkyFile's perspective there's absolutely nothing that can be done to remedy the situtation if either the path is invalid or file_get_contents fails. A truly exceptional situation ;)

But is there any value for your user to know that you've stumbled upon an wrong file path, somewhere in your code? For example:

class Welcome extends Controller {

    public function index() {

        /**
         * Ah, let's show user this file she asked for
         */                 
        try {
            $file = new File("HelloWorld.txt");
            $contents = $file->getContents();   
            echo $contents;
        } catch(\Exception $e) {
            log($e->getMessage());

            echo "Sorry, I'm having a bad day!"; 
        }                           
    }        
}

Other than telling people you're having a bad day, your options are:

  1. Fallback

    Do you have another way of getting the information? In my simple example above, it doesn't seem likely, but consider a master / slave database schema. The master may have failed to respond but maybe, just maybe, the slave is still out there (or vice versa).

  2. Is it the user's fault?

    Did the user submit faulty input? Well, tell her about it. You can either bark an error message, or be nice and accompany that error message with a form so she can type in the correct path.

  3. Is it your fault?

    And by you, I mean anything that's not the user, so that ranges from you typing a wrong file path, to something going awry in your server. Strictly speaking, it's time for a 503 HTTP error, as, well, the service is unavailable. CI has a show_404() function, you can easily build show_503().

Word of advice, you should take into consideration rogue exceptions. CodeIgniter is a messy piece of code, and you never know when an exception will pop up. Similarly, you may forget about your own exceptions, and the safest option is to implement a catch all exception handler. In PHP you can do that with set_exception_handler:

function FunkyExceptionHandler($exception) {
    if(ENVIRONMENT == "production") {
        log($e->getMessage());
        show_503();
    } else {
        echo "Uncaught exception: " , $exception->getMessage(), "\n";
    }   
}

set_exception_handler("FunkyExceptionHandler");

And you can also take care of rogue errors, via set_error_handler. You can either write the same handler as for exceptions, or alternatively convert all errors to ErrorException and let your exception handler deal with them:

function FunkyErrorHandler($errno, $errstr, $errfile, $errline) {
    // will be caught by FunkyExceptionHandler if not handled
    throw new ErrorException($errstr, 0, $errno, $errfile, $errline);
}

set_error_handler("FunkyErrorHandler");
share|improve this answer
    
This was really informative, cheers! –  Jimbo May 10 '13 at 14:33

Exceptions should be used when allowing the code to continue results in some kind of fundamental failure.

Generally speaking, you don't design an app excepting it to throw exceptions at runtime; You don't throw exceptions yourself as cheap GOTOs - you do not use exceptions for flow control.

A database error is an exception, of the examples you've given they are all the same in that they are all out of your control and something you should anticipate could occur - with the possible exception of a unique-key violation (it's better to test for a unique key violation and tell the user "sorry, that x is already taken" than to get as far as to need to catch an exception to detect that).

An exception does not mean showing users text they shouldn't be seeing. If you're doing that it is wrong but it's wrong for a lot more reasons that "don't use exceptions". If you're not displaying errors directly to the user but catching them and rendering a User friendly 500 error message - you're handling exceptions correctly in terms of user experience and not showing malicious users details they can use as an exploit.

So when to use exceptions?

This (contrived) example is wrong, don't do this :

function whatever() {
    ...
    try {
        $this->validate();
        $this->stickinthedb();
    } catch (Exception $e) {
        return $this->renderError($e);
    }
    ...
}

function validate() {
    foreach($rules as $rule) {
        if (!$this>$rule()) {
            throw new FailedValidationException($rule);
         }
    }
    return true;
}

It's wrong because it's using exceptions instead of an if/then/else block - and in the act preventing the reporting of multiple validation errors at once. In essence, your app should never need exceptions to function.

This is a (contrived) valid example:

function whatever() {
    ...
    if (!class_exists($dynamic)) {
        throw new MissingClassException($dynamic);
    }
    new $dynamic($config);      
    ...
}

It's right because it gives the developer more information about what's gone wrong, whilst not interfering with the normal code execution. Also, assuming it's handled correctly - the end user sees the same as the exception not being present (some kind of system-error message)

share|improve this answer
    
I dislike your validation example because you could put all errors into a list and then throw a ValidationException when the list is not empty with the list as data. I'm pretty sure that's how most modern systems work (JSF, Enterprise Library, ASP.NET MVC, see discussion with MainMa and msdn links). You could also stop validation when the first error is encountered with any other way of error handling, if coded wrongly. –  Falcon Feb 4 '12 at 22:37
    
The guy is asking about php; not jsf, .net etc. Irrespective of the language, using exceptions in 'normal' code is a mistake. –  AD7six Feb 4 '12 at 22:45
    
I don't think so. If you code with a "fail early" mentality, then exceptions are way better than for example status codes, which are much more prone to corrupt state and lead to errors that a harder to find and possibly have a much greater impact. Also, I'm talking about OO design practices here and that's quite independent of the language. I just used those famous frameworks as examples. But I don't say you should use exceptions to structure a program flow in general. –  Falcon Feb 4 '12 at 22:49
1  
what you are describing is a lot of assumptions and using exceptions as gotos - IMO –  AD7six Feb 4 '12 at 22:53
    
No, I'm just preferring implicit propagation over explicit complexity. The goto argument is non-sense imho. –  Falcon Feb 4 '12 at 22:54

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.