Error handling in PHP

Photo by JM Lova on Unsplash

Error handling in PHP

PHP Dec 21, 2022

Errors

Varieties in the bug family

Before taming bugs, I would recommend studying each species and paying attention to the brightest representatives separately.

To ensure that no error goes unnoticed, you need to enable tracking of all errors using the error_reporting() function , and use the display_errors directive to enable their display:

<?php
error_reporting(E_ALL);
ini_set('display_errors', 1);

Fatal errors

The most formidable type of errors are fatal ones, they can occur both during compilation and during the operation of the parser or PHP script, the script execution is interrupted.

# E_PARSE
This error occurs when you make a gross syntax error and the PHP interpreter does not understand what you want from it, for example, if you did not close the curly or parenthesis:

<?php
/**
 Parse error: syntax error, unexpected end of file
 */
{

Or written in an incomprehensible language:

<?php
/**
 Parse error: syntax error, unexpected '...' (T_STRING)
 */
There will be a parser error

Extra brackets are also found, and it doesn’t matter whether they are round or curly:

<?php
/**
 Parse error: syntax error, unexpected '}'
 */
}

I will note one important point - the code of the file in which you made a parse error will not be executed, therefore, if you try to enable the display of errors in the same file where the parser error occurred, it will not work:

<?php
// this code won't work
error_reporting(E_ALL);
ini_set('display_errors', 1);
 
// because right here
parser error

# E_ERROR
This error appears when PHP understood what you want, but it didn’t work out due to a number of reasons, it also interrupts the script execution, while the code before the error occurs will work:

The included file was not found:

/**
 Fatal error: require_once(): Failed opening required 'not-exists.php' (include_path='.:/usr/share/php:/usr/share/pear')
 */
require_once 'not-exists.php';

An exception was thrown (what kind of animal it is, I'll tell you a little later), but it was not processed:

/**
 Fatal error: Uncaught exception 'Exception'
 */
throw new Exception();

When trying to call a non-existent class method:

/**
 Fatal error: Call to undefined method stdClass::notExists()
 */
$stdClass = new stdClass();
$stdClass->notExists();

Lack of free memory (more than specified in the memory_limit directive ) or something like this:

/**
 Fatal Error: Allowed Memory Size
 */
$arr = array();
 
while (true) {
    $arr[] = str_pad(' ', 1024);
}
Very often happens when reading or downloading large files, so be careful with the issue of memory consumption

Recursive function call. In this example, it ended at the 256th iteration, because this is how it is written in the xdebug settings :

/**
 Fatal error: Maximum function nesting level of '256' reached, aborting!
 */
function deep() {
    deep();
}
deep();

Not fatal

This type does not interrupt the execution of the script, but they are usually found by the tester, and they are the ones that cause the most trouble for novice developers.

# E_WARNING
Often occurs when you include a file using include, but it does not appear on the server or you made a mistake when specifying the path to the file:

/**
 Warning: include_once(): Failed opening 'not-exists.php' for inclusion
 */
include_once 'not-exists.php';

It happens if you use the wrong type of arguments when calling functions:

/**
 Warning: join(): Invalid arguments passed
 */
join('string', 'string');

There are a lot of them, and it makes no sense to list them all ...

# E_NOTICE
These are the most common errors, moreover, there are fans of turning off error output and riveting them all day long. Occurs with a number of trivial errors.

When accessing an undefined variable:

/**
 Notice: Undefined variable: a
 */
echo $a;

When accessing a non-existent array element:

<?php
/**
 Notice: Undefined index: a
 */
$b = array();
$b['a'];

When accessing a non-existent constant:

/**
 Notice: Use of undefined constant UNKNOWN_CONSTANT - assumed 'UNKNOWN_CONSTANT'
 */
echo UNKNOWN_CONSTANT;

When not converting data types:

/**
 Notice: Array to string conversion
 */
echo array();

To avoid such errors - be careful, and if the IDE tells you about something - do not ignore it:

PHP E_NOTICE in PHPStorm

# E_STRICT
These are errors that will teach you how to write code correctly so that you are not ashamed, especially since the IDE shows you these errors right away. For example, if a non-static method is called as a static one, then the code will work, but this is somehow wrong, and serious errors may appear if the class method is later changed and a call to $this:

/**
 Strict standards: Non-static method Strict::test() should not be called statically
 */
class Strict { 
    public function test() { 
        echo 'Test'; 
    } 
}
 
Strict::test();

# E_DEPRECATED
This is how PHP will complain if you use deprecated functions (i.e. those that are marked as deprecated and will not be in the next major release):

/**
 Deprecated: Function split() is deprecated
 */
 
// popular function, still not removed from PHP
// deprecated since 5.3
split(',', 'a,b');

In my editor, such functions will be crossed out:

PHP E_DEPRECATED in PHPStorm

Processed

This type, which the code developer himself breeds, I haven’t seen them for a long time, I don’t recommend you start them:

  • E_USER_ERROR- critical error
  • E_USER_WARNING- not a critical error
  • E_USER_NOTICE– messages that are not errors

Separately, it is worth noting E_USER_DEPRECATEDthat this type is still used very often in order to remind the programmer that a method or function is obsolete and it is time to rewrite the code without using it. To generate this and similar errors, use the trigger_error() function :

/**
 * @deprecated Deprecated since version 1.2, to be removed in 2.0
 */
function generateToken() {
    trigger_error('Function `generateToken` is deprecated, use class `Token` instead', E_USER_DEPRECATED);
    // ...
    // code ...
    // ...
}

Now that you have become familiar with most types and types of errors, it's time to voice a little explanation on how the directive works display_errors:
  • if display_errors = on, then in case of an error, the browser will receive html with the error text and code 200
  • if display_errors = off, then for fatal errors the response code will be 500 and the result will not be returned to the user, for other errors, the code will work incorrectly, but will not tell anyone about it

Taming

There are 3 functions for dealing with errors in PHP:

  • set_error_handler() - sets the handler for errors that do not terminate the script (i.e. for non-fatal errors)
  • error_get_last() - Gets information about the last error
  • register_shutdown_function() - registers a handler that will be run when the script ends. This function is not directly related to error handlers, but is often used for this.

Now some details about error handling using set_error_handler(), as arguments this function takes the name of the function that will be entrusted with the mission of error handling and the types of errors that will be tracked. An error handler can also be a class method, or an anonymous function, as long as it takes the following list of arguments:

  • $errno– the first argument contains the error type as an integer
  • $errstr- the second argument contains the error message
  • $errfile- optional third argument contains the name of the file in which the error occurred
  • $errline- optional fourth argument contains the line number where the error occurred
  • $errcontext- optional fifth argument contains an array of all variables that exist in the scope where the error occurred

If the handler returns true, then the error will be considered handled and the script execution will continue, otherwise, the standard handler will be called, which logs the error and, depending on its type, continues the script execution or terminates it. Here is an example handler:

Tags

Anurag Deep

Logical by Mind, Creative by Heart