Copied!
<?php namespace Example\Tool; class ErrorLogging { private static ?\Maknz\Slack\Client $client = null; /** * @var array<string,bool> */ private static array $messages = []; /** * @var array<string, bool> */ private static array $pages = []; private static ?\Example\Setting\Slack $settings = null; public function __construct() { self::$settings = new \Example\Setting\Slack();	\register_shutdown_function([self::class, 'check_for_fatal']);	\set_error_handler([self::class, 'log_error'], \E_ALL);	\set_exception_handler([self::class, 'log_exception']); //	\ini_set('display_errors', 'off');	\error_reporting(\E_ALL);	} /** * Checks for a fatal error, work around for set_error_handler not working on fatal errors. */ public static function check_for_fatal() : bool {	$error = \error_get_last(); if ($error && \E_ERROR == $error['type'])	{ self::log_error($error['type'], $error['message'], $error['file'], $error['line']);	} return false;	} public static function clearErrorMessages() : void { self::$messages = [];	} public static function debug(mixed $message, string $location = '') : void { if (empty(self::$settings->optional('debug')))	{ return;	}	$bt = \debug_backtrace(); if (! isset($bt[0]['file']))	{ if (\strlen($location))	{	$location .= ': ';	} self::sendMessage($location . \print_r($message, true)); return;	}	$src = \file($bt[0]['file']);	$line = $src[$bt[0]['line'] - 1];	\preg_match('#' . __FUNCTION__ . '\((.+)\)#', $line, $match);	$max = \strlen($match[1] ?? '');	$varname = '';	$c = 0; for ($i = 0; $i < $max; ++$i)	{ if ('(' == $match[1][$i])	{	++$c;	} elseif (')' == $match[1][$i])	{	--$c;	} if ($c < 0)	{ break;	}	$varname .= $match[1][$i];	}	$at = ''; if (\strlen($location))	{	$at = "({$location})";	} self::sendMessage("{$varname} {$at}: " . \print_r($message, true));	} /** * @return array<string> */ public static function getErrorMessages() : array { return \array_keys(self::$messages);	} /** * Error handler, passes flow over the exception logger with new ErrorException. */ public static function log_error(int $num, string $str, string $file, int $line, mixed $context = null) : bool { self::log_exception(new \ErrorException($str, 0, $num, $file, $line)); return false;	} /** * Uncaught exception handler. */ public static function log_exception(\Throwable $e) : bool {	$errorText = $e->getMessage(); if (isset(self::$messages[$errorText]))	{ return false;	} self::$messages[$errorText] = true;	$link = ($_SERVER['SERVER_NAME'] ?? '') . ($_SERVER['REQUEST_URI'] ?? ''); // track one error per file if using Slack if (self::$client)	{ if (isset(self::$pages[$link]) && empty(self::$settings->optional('all')))	{ return false;	} self::$pages[$link] = true;	}	$file = \str_replace('/', '\\', $e->getFile());	$dir = \str_replace('/', '\\', PROJECT_ROOT . '\\');	$file = \str_replace($dir, '', $file);	$message = "{$errorText};\nFile: {$file}; Line: {$e->getLine()};"; self::sendMessage($message); return false;	} public static function sendMessage(string $message, string $type = 'error') : void { self::initialize(); if (! self::$client)	{ return;	} try	{	$link = ($_SERVER['REQUEST_SCHEME'] ?? 'http') . '://' . ($_SERVER['SERVER_NAME'] ?? 'localhost') . ($_SERVER['REQUEST_URI'] ?? '') . "\n"; self::$client->send($link . $message);	} catch (\Exception $e)	{	}	} public static function warning(string $message) : void { self::sendMessage($message, 'warning');	} private static function initialize() : void { if (! self::$client && self::$settings && self::$settings->optional('LoggingWebhook') && \strlen(self::$settings->optional('LoggingWebhook')) > 20)	{	$guzzle = new \GuzzleHttp\Client(['connect_timeout' => 1, 'timeout' => 1, 'verify' => false, 'http_errors' => false]); self::$client = new \Maknz\Slack\Client(self::$settings->optional('LoggingWebhook'), [], $guzzle);	}	}	} 
© 2025 Bruce Wells