Closes #283: Uses orginal PR as base for a recode of Errors.

This commit is contained in:
Phil Sturgeon
2014-02-17 11:22:18 -05:00
parent 419dba12a0
commit 0a70db7178

View File

@@ -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 "<stdin>", line 1, in <module>
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/