Core PHP 14 programs with output 15 Q/A 5 MCQs

Learning Objectives – after this chapter you will be able to:

  • Handle errors with die(), custom error handlers and trigger_error().
  • Know PHP's error report levels and configure error reporting and logging.
  • Send error messages by e-mail with error_log().
  • Use exceptions: try, throw, catch, finally, custom exception classes, multiple catches and re-throwing.
  • Set a top-level exception handler and understand PHP 8's Error/Throwable hierarchy.
PHP Error Handling

The default error handling in PHP is very simple: an error message with the file name, line number and a description of the error is sent to the browser.

When creating scripts and web applications, error handling is an important part. If your code lacks error-checking, your program may look very unprofessional and you may be open to security risks (error messages can reveal file paths and other internal details). This chapter shows different error-handling methods:

  • Simple die() statements
  • Custom errors and error triggers
  • Error reporting and logging
  • Exceptions
Basic Error Handling – die()

The first example simply opens a text file:

File: htdocs/phpbook/ch20/open1.php
<?php
$file = fopen("welcome.txt", "r");
?>
OUTPUT browser · http://localhost/phpbook/ch20/open1.php
Warning: fopen(welcome.txt): Failed to open stream: No such file or directory in /opt/lampp/htdocs/phpbook/ch20/open1.php on line 2

If the file does not exist you get a warning like the one above. To prevent the user from seeing such a message, test whether the file exists before trying to access it:

File: htdocs/phpbook/ch20/open2.php
<?php
if (!file_exists("welcome.txt")) {
    die("File not found");
} else {
    $file = fopen("welcome.txt", "r");
}
?>
OUTPUT browser · http://localhost/phpbook/ch20/open2.php
File not found

This is better than the earlier code because it uses a simple error-handling mechanism to stop the script after the error. However, simply stopping the script is not always the right way. Let us look at alternative functions for handling errors.

Creating a Custom Error Handler

Creating a custom error handler is quite simple: we write a special function that is called when an error occurs. The function must accept at least two parameters (the error level and the error message) and can accept up to four (optionally the file and the line number):

Syntax
error_function(error_level, error_message, error_file, error_line)
ParameterDescription
error_levelRequired. The error report level of the error – a number (see the table below).
error_messageRequired. The error message.
error_fileOptional. The file name in which the error occurred.
error_lineOptional. The line number on which the error occurred.

PHP 5 passed a fifth parameter, error_context (an array of all variables in scope). It was deprecated in PHP 7.2 and is no longer passed in PHP 8.

Error report levels
ValueConstantDescription
1E_ERRORFatal run-time error. Execution of the script is halted.
2E_WARNINGNon-fatal run-time error. Execution is not halted. (In PHP 8 "Undefined variable" is a warning.)
4E_PARSECompile-time parse (syntax) error.
8E_NOTICERun-time notice – something that might be an error.
256E_USER_ERRORFatal user-generated error, set with trigger_error().
512E_USER_WARNINGNon-fatal user-generated warning.
1024E_USER_NOTICEUser-generated notice (the default of trigger_error()).
2048E_STRICTSuggestions for better code (part of E_ALL since PHP 5.4).
4096E_RECOVERABLE_ERRORCatchable fatal error.
8192E_DEPRECATEDUse of features that will be removed in future versions.
32767E_ALLAll errors and warnings (the value in PHP 8).

Now let us create a function to handle errors:

function customError($errno, $errstr)
{
    echo "<b>Error:</b> [$errno] $errstr<br>";
    echo "Ending Script";
    die();
}

It receives the error level and message, prints them and ends the script.

Setting the Error Handler

PHP's default error handler is the built-in one. set_error_handler() makes our function the default for the rest of the script. A second parameter can restrict it to certain error levels; here we handle all errors. We test it by printing a variable that does not exist:

File: htdocs/phpbook/ch20/handler.php
<?php
// error handler function
function customError($errno, $errstr)
{
    echo "<b>Error:</b> [$errno] $errstr";
}
// set error handler
set_error_handler("customError");
// trigger error
echo($test);
?>
OUTPUT browser · http://localhost/phpbook/ch20/handler.php
Error: [2] Undefined variable $test

(In PHP 7 this was a notice, level 8; PHP 8 raised "Undefined variable" to a warning, level 2.)

Triggering an Error

In a script where users enter data, it is useful to trigger errors when illegal input occurs. In PHP this is done with trigger_error(). In this example an error occurs if the $test variable is bigger than 1:

File: htdocs/phpbook/ch20/trigger.php
<?php
$test = 2;
if ($test > 1) {
    trigger_error("Value must be 1 or below");
}
echo "<br>Script continues after a notice.";
?>
OUTPUT browser · http://localhost/phpbook/ch20/trigger.php
Notice: Value must be 1 or below in /opt/lampp/htdocs/phpbook/ch20/trigger.php on line 4

Script continues after a notice.

An error can be triggered anywhere in a script, and a second parameter specifies the level:

  • E_USER_ERROR – fatal user-generated run-time error; execution is halted.
  • E_USER_WARNING – non-fatal user-generated warning; execution continues.
  • E_USER_NOTICE – the default; a user-generated notice.

In the next example an E_USER_WARNING occurs if $test is bigger than 1; our custom handler then ends the script:

File: htdocs/phpbook/ch20/trigger2.php
<?php
// error handler function
function customError($errno, $errstr)
{
    echo "<b>Error:</b> [$errno] $errstr<br>";
    echo "Ending Script";
    die();
}
// set error handler only for E_USER_WARNING
set_error_handler("customError", E_USER_WARNING);
// trigger error
$test = 2;
if ($test > 1) {
    trigger_error("Value must be 1 or below", E_USER_WARNING);
}
?>
OUTPUT browser · http://localhost/phpbook/ch20/trigger2.php
Error: [512] Value must be 1 or below
Ending Script
Error Reporting and Logging

Which errors are reported and where they go is controlled in php.ini or at run time:

php.ini (development)
error_reporting = E_ALL
display_errors = On          ; show errors in the browser – development only
log_errors = On
error_log = "C:\xampp\php\logs\php_error_log"

On a production server set display_errors = Off and keep log_errors = On, so visitors never see internal details but you can read them in the log. In a script, error_reporting(E_ALL & ~E_NOTICE) or ini_set('display_errors', '0') change the settings for that script only.

Sending an error message by e-mail

By default PHP sends errors to the server's logging system or a file, depending on the error_log setting. With the error_log() function you can send a message to a specific file or a remote destination. Sending error messages to yourself by e-mail is a good way of being notified of specific errors:

Syntax
error_log(message, message_type, destination, extra_headers)
// message_type: 0 = system log, 1 = e-mail, 3 = append to a file, 4 = SAPI handler
File: htdocs/phpbook/ch20/errormail.php
<?php
// error handler function
function customError($errno, $errstr)
{
    echo "<b>Error:</b> [$errno] $errstr<br>";
    echo "Webmaster has been notified";
    error_log("Error: [$errno] $errstr", 1,
        "someone@example.com", "From: webmaster@example.com");
}
// set error handler
set_error_handler("customError", E_USER_WARNING);
// trigger error
$test = 2;
if ($test > 1) {
    trigger_error("Value must be 1 or below", E_USER_WARNING);
}
?>
OUTPUT browser · http://localhost/phpbook/ch20/errormail.php
Error: [512] Value must be 1 or below
Webmaster has been notified

The mail received from the code above contains: Error: [512] Value must be 1 or below. This should not be used for all errors – regular errors should be logged on the server with the default PHP logging system.

File: htdocs/phpbook/ch20/errorfile.php
<?php
error_log(date("Y-m-d H:i:s") . " Login failed for user 'guest'\n", 3, "app_errors.log");
error_log(date("Y-m-d H:i:s") . " Payment gateway timeout\n", 3, "app_errors.log");
echo "Log file contents:<pre>" . file_get_contents("app_errors.log") . "</pre>";
?>
OUTPUT browser · http://localhost/phpbook/ch20/errorfile.php
Log file contents:
2026-10-22 12:10:21 Login failed for user 'guest'
2026-10-22 12:10:21 Payment gateway timeout
Exceptions

Exceptions are used to change the normal flow of a script if a specified error (exceptional condition) occurs. With PHP 5 came this object-oriented way of dealing with errors. When an exception is triggered, normally:

  • The current code state is saved.
  • Code execution switches to a predefined (custom) exception handler.
  • Depending on the situation, the handler may resume execution from the saved state, terminate the script, or continue from a different location in the code.

Exceptions should only be used for error conditions, not as a way to jump to another place in the code.

Basic use of exceptions

When an exception is thrown, the code following it is not executed, and PHP looks for the matching catch block. If an exception is not caught, a fatal error with an "Uncaught Exception" message is issued. Let us throw an exception without catching it:

File: htdocs/phpbook/ch20/uncaught.php
<?php
// create function with an exception
function checkNum($number)
{
    if ($number > 1) {
        throw new Exception("Value must be 1 or below");
    }
    return true;
}
// trigger exception
checkNum(2);
?>
OUTPUT browser · http://localhost/phpbook/ch20/uncaught.php
Fatal error: Uncaught Exception: Value must be 1 or below in /opt/lampp/htdocs/phpbook/ch20/uncaught.php:6 Stack trace: #0 /opt/lampp/htdocs/phpbook/ch20/uncaught.php(11): checkNum() #1 {main} thrown in /opt/lampp/htdocs/phpbook/ch20/uncaught.php on line 6
try, throw and catch

To avoid the error above, write proper exception-handling code:

  • try – a function that may throw an exception is called inside a try block. If no exception is triggered, the code continues as normal; if it is, the exception is "thrown".
  • throw – this is how you trigger an exception. Each throw should have at least one catch.
  • catch – a catch block retrieves an exception and receives an object containing the exception information.
  • finally (PHP 5.5) – a block that always runs after try/catch, whether or not an exception occurred; used for clean-up.
File: htdocs/phpbook/ch20/trycatch.php
<?php
// create function with an exception
function checkNum($number)
{
    if ($number > 1) {
        throw new Exception("Value must be 1 or below");
    }
    return true;
}
// trigger exception in a "try" block
try {
    checkNum(2);
    // If the exception is thrown, this text will not be shown
    echo 'If you see this, the number is 1 or below';
}
// catch exception
catch (Exception $e) {
    echo 'Message: ' . $e->getMessage() . "<br>";
    echo 'Line: ' . $e->getLine();
}
finally {
    echo "<br>finally block: always executed";
}
?>
OUTPUT browser · http://localhost/phpbook/ch20/trycatch.php
Message: Value must be 1 or below
Line: 6
finally block: always executed

Example explained:

  1. The checkNum() function checks whether a number is greater than 1. If it is, an exception is thrown.
  2. checkNum() is called inside a try block, and the exception is thrown.
  3. The catch block retrieves the exception and creates an object $e containing the exception information.
  4. The error message is printed by calling $e->getMessage(); getLine(), getFile(), getCode() and getTraceAsString() give more details.
Creating a Custom Exception Class

To create a custom exception, write a class that extends PHP's Exception class. It inherits all properties and methods of Exception, and you can add your own functions.

File: htdocs/phpbook/ch20/customex.php
<?php
class customException extends Exception
{
    public function errorMessage()
    {
        // error message
        $errorMsg = 'Error on line ' . $this->getLine() . ' in ' . basename($this->getFile())
            . ': <b>' . $this->getMessage() . '</b> is not a valid E-Mail address';
        return $errorMsg;
    }
}
$email = "someone@example...com";
try {
    // check if the address is valid
    if (filter_var($email, FILTER_VALIDATE_EMAIL) === FALSE) {
        // throw exception if email is not valid
        throw new customException($email);
    }
} catch (customException $e) {
    // display custom message
    echo $e->errorMessage();
}
?>
OUTPUT browser · http://localhost/phpbook/ch20/customex.php
Error on line 17 in customex.php: someone@example...com is not a valid E-Mail address

The new class is a copy of the old exception class with an added errorMessage() function. Because it inherits from Exception, we can use methods such as getLine(), getFile() and getMessage().

Multiple Exceptions

A script can use several exceptions to check several conditions, with different exception classes returning different error messages:

File: htdocs/phpbook/ch20/multiex.php
<?php
class customException extends Exception
{
    public function errorMessage()
    {
        return 'Error on line ' . $this->getLine() . ' in ' . basename($this->getFile())
            . ': <b>' . $this->getMessage() . '</b> is not a valid E-Mail address';
    }
}
$email = "someone@example.com";
try {
    // check if the address is valid
    if (filter_var($email, FILTER_VALIDATE_EMAIL) === FALSE) {
        throw new customException($email);
    }
    // check for "example" in the mail address
    if (strpos($email, "example") !== FALSE) {
        throw new Exception("$email is an example e-mail");
    }
} catch (customException $e) {
    echo $e->errorMessage();
} catch (Exception $e) {
    echo $e->getMessage();
}
?>
OUTPUT browser · http://localhost/phpbook/ch20/multiex.php
someone@example.com is an example e-mail

The address is valid, so the first condition does not throw; the second condition throws a normal Exception because the address contains "example", and the second catch block handles it. If there were no customException catch, only the base Exception catch, the exception would be handled there. Since PHP 7.1 one block can catch several types: catch (TypeA | TypeB $e).

Re-throwing Exceptions

Sometimes you want to handle an exception differently from the standard way. It is possible to throw an exception a second time inside a catch block. A script should hide system errors from users: system errors matter to the programmer but not to the user, so you can re-throw the exception with a user-friendly message.

File: htdocs/phpbook/ch20/rethrow.php
<?php
class customException extends Exception
{
    public function errorMessage()
    {
        return $this->getMessage() . ' is not a valid E-Mail address.';
    }
}
$email = "someone@example.com";
try {
    try {
        // check for "example" in mail address
        if (strpos($email, "example") !== FALSE) {
            // throw exception if email is not valid
            throw new Exception($email);
        }
    } catch (Exception $e) {
        // re-throw exception
        throw new customException($email);
    }
} catch (customException $e) {
    // display custom message
    echo $e->errorMessage();
}
?>
OUTPUT browser · http://localhost/phpbook/ch20/rethrow.php
someone@example.com is not a valid E-Mail address.

If an exception is not caught in its current try block, PHP looks for a catch block on "higher levels".

Setting a Top-Level Exception Handler

set_exception_handler() sets a user-defined function to handle all uncaught exceptions:

File: htdocs/phpbook/ch20/tophandler.php
<?php
function myException($exception)
{
    echo "<b>Exception:</b> " . $exception->getMessage();
}
set_exception_handler('myException');
throw new Exception('Uncaught Exception occurred');
?>
OUTPUT browser · http://localhost/phpbook/ch20/tophandler.php
Exception: Uncaught Exception occurred

There is no catch block in this code; instead the top-level exception handler is triggered. Use it to catch exceptions that slip through everything else (and, for example, log them and show a friendly page).

Errors as Exceptions in PHP 8

Since PHP 7, most fatal errors are thrown as objects of the class Error, so they can be caught too. Both Exception and Error implement the interface Throwable:

Throwable
 ├── Exception  (RuntimeException, InvalidArgumentException, mysqli_sql_exception, …)
 └── Error      (TypeError, ValueError, ArithmeticError → DivisionByZeroError, …)
File: htdocs/phpbook/ch20/throwable.php
<?php
function divide(int $a, int $b): int
{
    return intdiv($a, $b);
}
try {
    echo divide(10, 0);
} catch (DivisionByZeroError $e) {
    echo get_class($e) . ": " . $e->getMessage() . "<br>";
}
try {
    echo strlen();               // wrong number of arguments
} catch (Throwable $t) {
    echo get_class($t) . ": " . $t->getMessage();
}
?>
OUTPUT browser · http://localhost/phpbook/ch20/throwable.php
DivisionByZeroError: Division by zero
ArgumentCountError: strlen() expects exactly 1 argument, 0 given
Rules for Exceptions
  • Code may be surrounded by a try block to help catch potential exceptions.
  • Each try block or throw must have at least one corresponding catch (or finally) block.
  • Multiple catch blocks can be used to catch different classes of exceptions.
  • Exceptions can be thrown (or re-thrown) in a catch block within a try block.
  • A simple rule: if you throw something, you have to catch it.
Key Takeaways
  • die()/exit() stop a script with a message; check conditions such as file_exists() first.
  • set_error_handler() installs a custom function receiving level, message, file and line.
  • trigger_error() raises E_USER_NOTICE, E_USER_WARNING or E_USER_ERROR.
  • In production: display_errors = Off, log_errors = On; error_log() writes to a log, a file or e-mail.
  • Exceptions: try / throw / catch / finally; extend Exception for custom types; catch several types; re-throw with friendly messages.
  • set_exception_handler() handles uncaught exceptions; PHP 8 throws Error objects – catch Throwable for both.
Program File

Extract the ZIP into C:\xampp\htdocs. It creates the folder phpbook/ch20 used in the file labels above; open the programs at http://localhost/phpbook/… with Apache (and MySQL, where needed) started in the XAMPP Control Panel.

Question / Answer (15 questions)

Answer : It sends a message containing the error type, a description, the file name and the line number to the browser (when display_errors is on) and/or to the error log.

Answer : Without it applications look unprofessional, may stop in an uncontrolled way, and error messages can reveal internal details such as file paths that help attackers.

Answer : die("message") (an alias of exit) prints a message and stops the script; used after testing a condition such as !file_exists($f), it avoids raw PHP warnings.

Answer : At least two – the error level and the error message – and optionally the file name and the line number (four in PHP 8; the old fifth error_context parameter is no longer passed).

Answer : It makes a user-defined function the error handler for the rest of the script, optionally only for the error levels given in the second parameter.

Answer : E_USER_ERROR (256, fatal), E_USER_WARNING (512, non-fatal) and E_USER_NOTICE (1024, the default).

Answer : It was raised from a notice (E_NOTICE, 8) to a warning (E_WARNING, 2).

Answer : display_errors = Off so visitors see no internal details, and log_errors = On with error_log pointing to a log file, with error_reporting = E_ALL.

Answer : With error_log($message, 1, "admin@example.com", "From: webmaster@example.com"); – message type 1 sends an e-mail.

Answer : An object representing an exceptional condition that changes the normal flow of the script: when thrown, execution jumps to the nearest matching catch block.

Answer : try encloses code that may throw; throw raises an exception object; catch receives and handles a matching exception; finally contains code that always runs afterwards.

Answer : Define a class that extends Exception, optionally adding methods: class customException extends Exception { public function errorMessage() { … } }

Answer : Throwing a new (often user-friendly) exception from inside a catch block, so that a higher-level handler deals with it.

Answer : It registers a function that is called for any exception that is not caught by a try/catch block.

Answer : The interface implemented by both Exception and Error in PHP 7+; catching Throwable catches all exceptions and engine errors such as TypeError and DivisionByZeroError.
MCQ Test : Check Your Understanding (5 questions)

Select an option and press Check Answer, or answer all questions and press Submit Test to see your score. Each answer comes with an explanation.

Q1. Which function installs a user-defined error handler?

Show Answer

Correct Answer : B. set_error_handler()
set_error_handler() registers the function.

Q2. The default level of trigger_error() is:

Show Answer

Correct Answer : C. E_USER_NOTICE
Without a second argument it raises E_USER_NOTICE.

Q3. Which block always executes after try/catch?

Show Answer

Correct Answer : B. finally
finally runs whether or not an exception occurred.

Q4. A custom exception class must:

Show Answer

Correct Answer : B. Extend Exception
Custom exceptions inherit from Exception.

Q5. In PHP 8, both Exception and Error implement:

Show Answer

Correct Answer : A. Throwable
Catching Throwable catches both.

Bibliography/References

The notes on this page are the author’s own compilation from the e-book PHP: Basics to Advance. Every program was run on Apache with PHP 8 and MariaDB, and the output shown is the real result of that run. The works listed below were consulted and are cited for attribution and further reading. Product names and trademarks belong to their respective owners.

  1. The PHP Group. (n.d.). PHP Manual – Error Handling and Logging. https://www.php.net/manual/en/book.errorfunc.php
  2. The PHP Group. (n.d.). PHP Manual – Predefined Constants (error levels). https://www.php.net/manual/en/errorfunc.constants.php
  3. The PHP Group. (n.d.). PHP Manual – set_error_handler. https://www.php.net/manual/en/function.set-error-handler.php
  4. The PHP Group. (n.d.). PHP Manual – Exceptions. https://www.php.net/manual/en/language.exceptions.php
  5. The PHP Group. (n.d.). PHP Manual – Errors in PHP 7. https://www.php.net/manual/en/language.errors.php7.php