views:

592

answers:

4

How should I write error reporting modules in PHP? Say, I want to write a function in PHP: 'bool isDuplicateEmail($email)'. In that function, I want to check if the $email is already present in the database. It will return 'true', if exists. Else 'false'.

Now, the query execution can also fail, In that time I want to report 'Internal Error' to the user.

The function should not die with typical mysql error: die(mysql_error(). My web app has two interfaces: browser and email(You can perform certain actions by sending an email). In both cases it should report error in good aesthetic. Do I really have to use exception handling for this?

Can anyone point me to some good PHP project where I can learn how to design robust PHP web-app?

+1  A: 

Using MVC, i always use some sort of default error/exception handler, where actions with exceptions (and no own error-/exceptionhandling) will be caught.
There you could decide to answer via email or browser-response, and it will always have the same look :)

Karsten
+1, each interface to the business logic should be handling the display and response of the errors. Have it throw "DuplicateException", the Email/Web ui catches it, and changes it into HTML or a Mime message, as appropriate.
Richard Levasseur
A: 

I'd use a framework like Zend Framework that has a thorough exception handling mechanism built all through it.

Chris KL
A: 

Look into exception handling and error handling in the php manual. Also read the comments at the bottom, very useful.

There's aslo a method explained in those page how to convert PHP errors into exceptions, so you only deal with exceptions (for the most part).

Mario
There are those who believe that exceptions are glorified goto statements. While I wouldn't go that far, I would say that it makes it can make it difficult to follow code. I suppose it's pretty subjective, though.
Karim
Everything is a goto statement then.
Mario
Um. I guess you're saying that every expression leads to the next expression? I think that kind of misses my point. Consider that a thrown exception can send you not only to another part of the same function but to another area of the application entirely if not handled correctly.
Karim
Exceptions aren't idiot proof. Bad architecture is something else.
Mario
+1  A: 

In my PHP projects, I have tried several different tacts. I've come to the following solution which seems to work well for me:

First, any major PHP application I write has some sort of central singleton that manages application-level data and behaviors. The "Application" object. I mention that here because I use this object to collect generated feedback from every other module. The rendering module can query the application object for the feedback it deems should be displayed to the user.

On a lower-level, every class is derived from some base class that contains error management methods. For example an "AddError(code,string,global)" and "GetErrors()" and "ClearErrors". The "AddError" method does two things: stores a local copy of that error in an instance-specific array for that object and (optionally) notifies the application object of this error ("global" is a boolean) which then stores that error for future use in rendering.

So now here's how it works in practice:

Note that 'Object' defines the following methods: AddError ClearErrors GetErrorCodes GetErrorsAsStrings GetErrorCount and maybe HasError for convenience

// $GLOBALS['app'] = new Application();

class MyObject extends Object
{
     /**
      * @return bool Returns false if failed
      */
     public function DoThing()
     {
          $this->ClearErrors();
          if ([something succeeded])
          {
              return true;
          }
          else 
          {
              $this->AddError(ERR_OP_FAILED,"Thing could not be done");
              return false;
          }              
     }
}

$ob = new MyObject();
if ($ob->DoThing()) 
{
   echo 'Success.';
}
else 
{
   // Right now, i may not really care *why* it didn't work (the user
   // may want to know about the problem, though (see below).
   $ob->TrySomethingElse();
}

// ...LATER ON IN THE RENDERING MODULE
echo implode('<br/>',$GLOBALS['app']->GetErrorsAsStrings());

The reason I like this is because:

  1. I hate exceptions because I personally believe they make code more convoluted that it needs to be
  2. Sometimes you just need to know that a function succeeded or failed and not exactly what went wrong
  3. A lot of times you don't need a specific error code but you need a specific error string and you don't want to create an error code for every single possible error condition. Sometimes you really just want to use an "opfailed" code but go into some detail for the user's sake in the string itself. This allows for that flexibility
  4. Having two error collection locations (the local level for use by the calling algorithm and global level for use by rendering modules for telling the user about them) has really worked for me to give each functional area exactly what it needs to get things done.
Karim
Fail fast, crash hard. Exceptions are your friends. They get rid of these massive error checkups that riddles your main app. Use a global catcher if you must to hide errors from users and display a nice page.
Mario
I'm not sure which massive error "checkups" you're referring to, but the truth is you can make really bad code and really good code using both methods
Karim
Having to worry about FALSE or NULL or -1 returned on every functions you call, and handling it appropriately. Then there's all those places in your code where you do forget to check for them, leading to either silent errors or an app crashing 20 lines later, hard to debug.
Mario
Actually, it's just false or true and the flexibility in handling it or not is exactly the benefit. And if i'm understanding right, exception are much more complicated in that you can throw any number of types of exceptions and may or may not even handle it in the current function. very messy IMHO
Karim