How to Handle Errors and Exceptions in PHP

Every application, no matter how simple, can encounter errors — a database connection fails, a file isn't found, input doesn't match the expected format, and much more. PHP provide...

How to Handle Errors and Exceptions in PHP

Every application, no matter how simple, can encounter errors — a database connection fails, a file isn't found, input doesn't match the expected format, and much more. PHP provides two mechanisms for handling these situations: Error (PHP-level failures) and Exception (exceptional conditions that are thrown and can be caught). Understanding both is very important for building robust and easy-to-debug applications.

Types of Errors in PHP

PHP has several error levels, including:

  • E_ERROR — a fatal error, script execution stops.
  • E_WARNING — a warning, the script keeps running.
  • E_NOTICE — a minor notice (e.g. an undefined variable).
  • E_DEPRECATED — a deprecated function is used.
  • E_PARSE — a syntax error, the script can't run.

Configuring Error Display

In a development environment, display all errors. In production, hide them from the user but log them:

<?php
// For a development environment
ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
error_reporting(E_ALL);

// For a production environment
ini_set('display_errors', 0);
ini_set('log_errors', 1);
ini_set('error_log', '/path/to/error.log');
error_reporting(E_ALL);

Better yet, set this in the php.ini file or .htaccess and use environment variables to distinguish development and production mode.

The Basic try-catch Block

Exceptions are caught using a try-catch block:

<?php

function divide(int $a, int $b): float
{
    if ($b === 0) {
        throw new InvalidArgumentException("Cannot divide by zero!");
    }
    return $a / $b;
}

try {
    $result = divide(10, 2);
    echo "10 / 2 = $result\n"; // 10 / 2 = 5

    $result = divide(10, 0); // This will throw an exception
    echo "This line will not be executed";

} catch (InvalidArgumentException $e) {
    echo "Error: " . $e->getMessage() . "\n";
    echo "In file: " . $e->getFile() . " line " . $e->getLine();
}

Catching Multiple Exception Types

You can have several catch blocks to handle different exception types:

<?php

function processFile(string $path): string
{
    if (!file_exists($path)) {
        throw new RuntimeException("File not found: $path");
    }

    $content = file_get_contents($path);
    if ($content === false) {
        throw new RuntimeException("Failed to read file: $path");
    }

    if (strlen($content) === 0) {
        throw new LengthException("File is empty: $path");
    }

    return $content;
}

try {
    $data = processFile('/data/report.txt');
    echo "Content: $data";

} catch (LengthException $e) {
    echo "File is empty: " . $e->getMessage();

} catch (RuntimeException $e) {
    echo "Runtime error: " . $e->getMessage();

} catch (\Throwable $e) {
    // Catch all uncaught errors and exceptions
    echo "Unexpected error: " . $e->getMessage();
}

In PHP 8, use \Throwable (not \Exception) as a fallback to catch all types of errors and exceptions.

The finally Block

The finally block is always executed, whether an exception occurs or not — useful for cleaning up resources:

<?php

function readFile(string $path): void
{
    $handle = fopen($path, 'r');

    if ($handle === false) {
        throw new RuntimeException("Cannot open the file.");
    }

    try {
        while (($line = fgets($handle)) !== false) {
            echo $line;
        }
    } finally {
        // Always close the file even if an exception occurs
        fclose($handle);
        echo "\nFile has been closed.";
    }
}

Creating a Custom Exception

For a more structured application, create your own exception classes:

<?php

// Custom exception definition
class DatabaseException extends RuntimeException
{
    private string $query;

    public function __construct(string $message, string $query = '', int $code = 0, ?\Throwable $previous = null)
    {
        $this->query = $query;
        parent::__construct($message, $code, $previous);
    }

    public function getQuery(): string
    {
        return $this->query;
    }
}

class ValidationException extends \InvalidArgumentException
{
    private array $errors;

    public function __construct(array $errors)
    {
        $this->errors = $errors;
        parent::__construct("Validation failed: " . implode(', ', $errors));
    }

    public function getErrors(): array
    {
        return $this->errors;
    }
}

// Usage
try {
    throw new ValidationException(['Name is required', 'Email is invalid']);
} catch (ValidationException $e) {
    foreach ($e->getErrors() as $error) {
        echo "- $error\n";
    }
}

Global Error Handler

To catch PHP errors (not exceptions) globally and turn them into exceptions:

<?php

// Turn all errors into ErrorException so they can be caught with try-catch
set_error_handler(function (int $errno, string $errstr, string $errfile, int $errline): bool {
    throw new \ErrorException($errstr, $errno, 0, $errfile, $errline);
});

// Catch uncaught exceptions
set_exception_handler(function (\Throwable $e): void {
    error_log("Uncaught Exception: " . $e->getMessage() . " in " . $e->getFile());
    // Show a user-friendly error page
    http_response_code(500);
    echo "An error occurred. Our team is working on this issue.";
});

Conclusion

Good error and exception handling makes your PHP application more robust, easier to debug, and provides a better experience for users. Use the try-catch-finally block to handle exceptional conditions, create custom exceptions for domain-specific errors, and always distinguish between error display in development and production environments. With this approach, bugs are easier to find and the application can fail gracefully.

exception php error handling php try catch php php native error custom exception php php 8 error handling
Read Also

Here are some related articles that might help expand your knowledge:

Share this article
Back to Blog
🚀 Partner Recommendation

Need Premium Source Code & Business Apps?

Access Laravel applications, POS systems, School Management, Clinic Software, ERP solutions, and ready-to-use premium source code at GudangCode.

GudangCode
  • ✔ Premium Source Code
  • ✔ Ready-to-Use Systems
  • ✔ Lifetime Updates
  • ✔ Lifetime Membership
  • ✔ Daily App Updates
Join Membership →