devnotes.

Custom Exceptions and Error Reporting

You can define your own exception classes by extending Exception, giving each error condition a specific, self-documenting type:

class InsufficientFundsException extends Exception
{
    public function __construct(
        public readonly float $requested,
        public readonly float $available,
    ) {
        parent::__construct(
            "Requested $requested but only $available available."
        );
    }
}

function withdraw(float $amount, float $balance): float
{
    if ($amount > $balance) {
        throw new InsufficientFundsException($amount, $balance);
    }
    return $balance - $amount;
}

try {
    withdraw(500, 200);
} catch (InsufficientFundsException $e) {
    echo $e->getMessage();
    echo "Short by: " . ($e->requested - $e->available);
}

Error reporting settings control what gets shown or logged. In development, show everything:

ini_set('display_errors', 1);
error_reporting(E_ALL);

In production, never display raw errors to users (they can leak sensitive info) — log them instead:

ini_set('display_errors', 0);
ini_set('log_errors', 1);
ini_set('error_log', '/path/to/error.log');

A custom top-level error handler (set_error_handler()) and exception handler (set_exception_handler()) let you centralize logging, alerting, or converting PHP errors into exceptions for consistent handling across an app — this is exactly what frameworks like Laravel and Symfony do under the hood.

PHP Custom Exceptions and Error Reporting | DevNotes