After having an argument with my team because we all have different views on this sort of situation.. When is it actually acceptable to turn off PHP error messages, or to su
1 - You can turn off display_errors and turn on log_errors
@ini_set('log_errors','On');
@ini_set('display_errors','Off');
2 - You can use the default php Error and Logging functions & constants
See: http://www.w3schools.com/php/php_ref_error.asp
3 - You can implement your own set of error and logging functions with the PHP Filesystem
See: http://www.w3schools.com/php/php_ref_filesystem.asp
You never simply turn off error reporting entirely. You do turn off error display. Directly dumping errors to the screen is necessary during development (unless you have other methods which throw all errors in your face), in production you want the same error reporting but instead of it outputting visible errors, you want it to only log them. This can all be done using PHP's error reporting configuration settings.
If you want special custom error handling/logging, use a custom error handler.
As for @
, you never write your application in a way that it produces actual errors on whose behavior you rely. You write everything in a way that does not trigger errors. You only use @
when there's no way to avoid a possible error because you cannot write it any other way, and you expect an error and are handling it; then all you do it to suppress the inevitable error message.
Sorry, this is not a definite solution, but after several years of trial and error, I came up with the following practices, which are just my own, and work pretty well:
1 - Never use @ to suppress errors. Never use anything to blindly hide or ignore all errors. ALL errors are important, no error should be ignored.
2 - Do as RafaSashi suggested, turn on error logging and turn off display errors.
3 - Activate ALL error reporting, by using error_reporting = 2147483647
in PHP.INI. That will make PHP very picky with anything you may do wrongly, helping you learn more and stay up to date with future language deprecations and changes.
4 - You can also create you own error logging, to log exactly what you want, the way you want. Look up the manual for error_log()
. If you use it, you can even turn looging off, and start logging manually, that will give you full control of PHP's error logging system.
5 - I use OOP in all my PHP code, so I use exceptions everywhere, and I recommend the same for everyone. They're light-years ahead of simply error handling. Use this code to intercept all errors in your code and throw them as exceptions:
set_error_handler('ErrorHandler');
function ErrorHandler($Code, $Message)
{
throw new Exception($Message, $Code);
}
6 - Not showing ANY errors to the user is simply non-sense. Some errors should be shown, some should be hidden, and some should be shown as a generic issue (don't tell the user exactly what the problem is).
a) Errors that should be shown: everything caused by the user, like invalid form input or wrong behavior. This is quite obvious, but should be mentioned.
b) Errors that should be hidden: hide only the errors your code can handle and correct. For example, you can do a DB connection, and if it fails, you can try again. If the second attempt succeeds, go ahead, no one should ever know the first try failed. Just log it if you want, using error_log()
. Sometimes, variables don't exist yet, so check this with isset()
, and initialize them if needed. No need to report this as an error too.
c) Errors that should be shown as generic: most errors will fall in this category. You will not show the user things like PHP memory exhausted, or that a SMTP server is offline, or that a DB connection was refused. Just learn how to wrap dangerous code with a try
, use a catch to capture any error, and convert the message to something you can show to the user. Example:
try
{
// Dangerous code ahead: we will try to connect to the database, but it
// can be offline.
$mysqli = new mysqli("localhost", "user", "password", "database");
}
catch(Exception $e)
{
// If we're here, something bad happened during connection. Let's handle it.
// Notify staff, log error, do anything you can to get someone to quickly
// check the issue.
SendMailAdmin("Database connection Error, check ASAP.");
error_log("Database connection Error, check ASAP.");
// And show the user some message. You don't need to tell him about any
// detail regarding what truly caused the error.
die("A problem occurred in our servers. Our technical staff has been notified,
please try again in a few minutes.");
}
// If we're here, everything worked fine, so do your DB query and so on....
Instead of a die()
, you can use what you see fit: re-throw as another exception, do a header redirect to a generic error message or whatever you want.
7 - This is more advanced, but you can do it also: create you own exception hierarchy, like this:
class MVXException extends Exception {}
class ExMVXDB extends MVXException {}
class ExMVXDBRead extends ExMVXDB { }
class ExMVXDBWrite extends ExMVXDB { }
class ExMVXDBNotFound extends ExMVXDB { }
This is a simplification of the exceptions tree I have in my self-made framework. The beauty of this is that if you do a catch(ExMVXDB $e)
, you will catch ALL DB errors. But if you want to catch only a data writing operation, you can do a catch(ExMVXDBWrite $e)
.
That's it. Error handling is not simple, and there's no direct answer, but there are plenty of tools and good practices to help you choose what's best for you.