From 0a70db7178207b931f13a7d1e1d1d7b8570d9365 Mon Sep 17 00:00:00 2001 From: Phil Sturgeon Date: Mon, 17 Feb 2014 11:22:18 -0500 Subject: [PATCH] Closes #283: Uses orginal PR as base for a recode of Errors. --- _posts/07-02-01-Errors.md | 114 +++++++++++++++++++++++++++++--------- 1 file changed, 88 insertions(+), 26 deletions(-) diff --git a/_posts/07-02-01-Errors.md b/_posts/07-02-01-Errors.md index bbfc67f..c87ab37 100644 --- a/_posts/07-02-01-Errors.md +++ b/_posts/07-02-01-Errors.md @@ -4,52 +4,114 @@ isChild: true ## Errors {#errors_title} -PHP Errors differ to Exceptions in that they, Errors can halt the execution of your script depending on the level of -severity. Exceptions on the other hand can be caught using `try catch` statements. +In many "exception-heavy" programming languages, whenever anything goes wrong an exception will be thrown. This is +certainly a viable way to do things, but PHP is an "exception-light" programming language. While it does have +exceptions and more of the core is starting to use them when working with objects, most of PHP itself will try to keep +processing regardless of what happens, unless a fatal error happens. + +For example: + +{% highlight php %} +$ php -a +php > echo $foo; +Notice: Undefined variable: foo in php shell code on line 1 +{% endhighlight %} + +This is only a notice error, and PHP will happily carry on. This can be confusing for those from "exception-heavy" +languages, because referencing a missing variable in Python for example will throw an exception: + +{% highlight python %} +$ python +>>> print foo +Traceback (most recent call last): + File "", line 1, in +NameError: name 'foo' is not defined +{% endhighlight %} + +The only real difference is that Python will freak out over any small thing, so that developers can be super sure any +potential issue or edge-case is caught, whereas PHP will keep on processing unless something extreme happens, at which +point it will throw an error and report it. ### Error Severity -PHP's built in error reporting and logging, allows for different levels of reporting via the use of Predefined -Constants. The three main constants are `E_ERROR`, `E_NOTICE`, and `E_WARNING`. +PHP has several levels of error severity. The three most common types of messages are errors, notices and warnings. +These have different levels of severity; `E_ERROR`, `E_NOTICE`, and `E_WARNING`. Errors are fatal run-time errors and +are usually caused by faults in your code and need to be fixed as they'll cause PHP to stop executing. Warnings are +non-fatal errors, execution of the script will not be halted. Notices are advisory messages caused by code that may or +may not cause problems during the execution of the script, execution is not halted. -The different levels of error severity have different meanings. The three most common types of messages are Errors, -Notices and Warnings. Errors are fatal run-time Errors and are usually caused by faults in your code and need to be -fixed as they'll cause execution to be halted. Warnings are non-fatal errors, execution of the script will continue -and dependant on settingsĀ the user may or not may see the Warning message. Notices are advisory messages caused by -code that may or may not cause problems during script execution, execution is not halted and again depending on -settings the user may or not see the Notice message. - -Another type of Error Message reported at compile time are `E_STRICT` messages, these messages are used to suggest -changes to your code to help ensure best interoperability and forward compatibility for your code. +Another type of error message reported at compile time are `E_STRICT` messages. These messages are used to suggest +changes to your code to help ensure best interoperability and forward compatibility with upcoming versions of PHP. ### Changing PHP's Error Reporting Behaviour Error Reporting can both be changed using PHP settings and PHP function calls. Using the built in PHP function `error_reporting()` you can set the level of errors for the duration of the script execution by passing one of the -Predefined Constants. For more information on this relating to application environments check -out the [Error Reporting][errorreport]. +Predefined Constants, meaning if you only want to see Warnings and Errors - but not Notices - then you can configure that: -As well as setting the level of error reporting during script execution you can also suppress Errors using the -Error Control Operator `@` by putting this operator at the beginning an expression. The use of this operator -is not advised and should never be used, using this operator is like admitting your code is bad and can fail over +{% highlight php %} +error_reporting(E_ERROR | E_WARNING | E_PARSE); +{% endhighlight %} + +You can also control wether or not errors are displayed to the screen (good for development) or hidden, and logged +(good for production). For more information on this check out the [Error Reporting][errorreport] section. + +### Inline Error Supression + +As well as setting the level of error reporting during script execution you can also suppress specific errors from being +displayed using the Error Control Operator `@`. You simply put this operator at the beginning an expression, and any +error that would be caused as a direct result of the specific expression will be silenced. + +{% highlight php %} +echo @$foo['bar']; +{% endhighlight %} + +This will output `$foo['bar']` if it exists, but will simply return a null and print nothing if the variable `$foo` or +`'bar'` key does not exist. + +This might seem like a good idea, but due to the way PHP actually handles `@` it is incredibly unperformant, and has the +unexpected effect of still actually logging the error anyway. If you have this code in a loop that runs 100 times in an +instance, and you run that 1 million times, then you've got 100 million lines in your logs. + +Instead, use the following: + +{% highlight php %} +echo isset($foo['bar']) ? $foo['bar'] : ''; +{% endhighlight %} + +This will be much quicker, and save filling up your logs with junk. [SitePoint] go a step further and say you should +[never suppress notices] with `@`. + +One instance where error suppression might make sense is where `fopen()` fails to find a file to load. You could check +for existence of the file before you try to load it, but if the file is deleted after the check and before the `fopen()` +(which might sound impossible, but it can happen) then `fopen()` will return false _and_ throw an error. This is +potentially something PHP should resolve, but is one case where error suppression might seem like the only valid +solution. * [Error Control Operators](http://php.net/manual/en/language.operators.errorcontrol.php) +* [SitePoint](http://www.sitepoint.com/) +* [never suppress notices](http://www.sitepoint.com/why-suppressing-notices-is-wrong/) -### Error Exceptions +### ErrorException's -Optionally you can throw your Errors as Exceptions using the `ErrorException` class, this class extends the `Exception` -class. This is a common practice and by passing errors off as Exceptions in development you can handle them better than -the usual result. By passing these Errors as Exceptions and not trying to catch them in Development the hope is that -you'll catch the Error and hopefully this will allow you to deal with the issue before it becomes a problem in a -Production Environment. -More information on this and details on how to use `ErrorException` with Error Handling can be found at +PHP is perfectly capable of being an "exception-heavy" programming language, and only requires a few lines of code to +make the switch. Basically you can throw your "errors" as "exceptions" using the `ErrorException` class, which extends the `Exception` class. + +This is a common practice implemented by a large number of modern frameworks such as Symfony and Laravel. By default +Laravel will display all errors as exceptions using the [Whoops!] package if the `app.debug` switch is turned on, then +hide them if the switch is turned off. + +By throwing errors as exceptions in development you can handle them better than the usual result, and if you see an +exception during development you can wrap it in a catch statement with specific instructions on how to handle the situation. Each exception you catch instantly makes your application that little bit more robust. + +More information on this and details on how to use `ErrorException` with error handling can be found at [ErrorException Class][errorexception]. * [Error Control Operators](http://php.net/manual/en/language.operators.errorcontrol.php) * [Predefined Constants for Error Handling](http://www.php.net/manual/en/errorfunc.constants.php) * [error_reporting](http://www.php.net/manual/en/function.error-reporting.php) -* [ErrorException Class][errorexception] * [Reporting][errorreport] [errorexception]: http://php.net/manual/en/class.errorexception.php [errorreport]: /#error_reporting +[Whoops!]: http://filp.github.io/whoops/