set_error_handler jako elegancki sposób na bolączki z PHP

Gdy PHP powstawało nikt nawet nie śnił, że to narzędzie znajdzie zastosowanie w dużych projektach informatycznych aniżeli tylko w prostych skryptach. Pewnym tego pokłosiem jest wprowadzenie mechanizmu wyjątków (https://www.php.net/manual/en/language.exceptions.php) dopiero w wersji 5. Niestety ze względu na kompatybilność sporo wbudowanych funkcji, struktur języka takich jak np. fopen(), mail(), dzielenie przez zero etc. nie zgłasza wyjątków a E_ERROR, E_WARNING.. (https://php.net/manual/en/errorfunc.constants.php).

Jeśli zamiast tego chcielibyśmy otrzymać wyjątek lub inaczej obsłużyć taką sytuacje to trzeba customizować obsługę błędów w PHP właśnie przez set_error_handler(). Poniżej przykład zaczerpnięty z Zend Mail (zendframework/zend-mail/src/Transport/Sendmail.php)

/**
 * Send mail using PHP native mail()
 *
 * @param  string $to
 * @param  string $subject
 * @param  string $message
 * @param  string $headers
 * @param  $parameters
 * @throws \Zend\Mail\Transport\Exception\RuntimeException
 */
public function mailHandler($to, $subject, $message, $headers, $parameters)
{
    set_error_handler([$this, 'handleMailErrors']);
    if ($parameters === null) {
        $result = mail($to, $subject, $message, $headers);
    } else {
        $result = mail($to, $subject, $message, $headers, $parameters);
    }
    restore_error_handler();

    if ($this->errstr !== null || ! $result) {
        $errstr = $this->errstr;
        if (empty($errstr)) {
            $errstr = 'Unknown error';
        }
        throw new Exception\RuntimeException('Unable to send mail: ' . $errstr);
    }
}

Z tego miejsca warto przypomnieć, że gdy już się customizuje error handler to należy zadbać o zapisanie kompletnej informacji o pochodzeniu błędu (komunikat, miejsce wywołania i inne dodatkowe informacje ułatwiające debugowanie).

Więcej w https://www.php.net/manual/en/function.set-error-handler.php