getTrace() as $frame) { $args = ""; if (isset($frame['args'])) { $args = array(); foreach ($frame['args'] as $arg) { if (is_string($arg)) { $args[] = "'" . $arg . "'"; } elseif (is_array($arg)) { $args[] = "Array"; } elseif (is_null($arg)) { $args[] = 'NULL'; } elseif (is_bool($arg)) { $args[] = ($arg) ? "true" : "false"; } elseif (is_object($arg)) { $args[] = get_class($arg); } elseif (is_resource($arg)) { $args[] = get_resource_type($arg); } else { $args[] = $arg; } } $args = join(", ", $args); } $rtn[] = sprintf( "#%s %s:%s %s(%s)", $count, isset($frame['file']) ? $frame['file'] : 'unknown file', isset($frame['line']) ? $frame['line'] : 'unknown line', (isset($frame['class'])) ? $frame['class'] . $frame['type'] . $frame['function'] : $frame['function'], $args ); $count++; } return $rtn; } function logError(string $err, string $errstr, string $errpath, array $trace) { $fdb = FileDB::db(ROOT . '/d_log/err_log.sqlite3', ROOT . '/f_install/sql/err_log.sql'); $date = date("Ymd_His"); $err = str_replace(ROOT, '{ROOT}', $err); $errstr = str_replace(ROOT, '{ROOT}', $errstr); $errpath = str_replace(ROOT, '{ROOT}', $errpath); $trace = array_map(function (string|array $text) { if (is_array($text)) { $text = Json::encode($text); } return str_replace(ROOT, '{ROOT}', $text); }, $trace); $owner = Util::get_client_ip(); $session = Session::getInstance(); if ($session->isLoggedIn(true)) { $owner .= '(' . $session->getUserID() . ',' . $session->userName . ')'; } $fdb->insert('err_log', [ 'date' => $date, 'err' => $err, 'errstr' => $errstr, 'errpath' => $errpath, 'trace' => Json::encode($trace), 'webuser' => $owner ]); } function logErrorByCustomHandler(int $errno, string $errstr, string $errfile, int $errline) { if (!(error_reporting() & $errno)) { // This error code is not included in error_reporting, so let it fall // through to the standard PHP error handler return false; } $e = new \Exception(); logError( getFriendlyErrorType($errno), $errstr, $errfile . ':' . $errline, getExceptionTraceAsString($e) ); return true; } set_error_handler("\\sammo\\logErrorByCustomHandler"); function logExceptionByCustomHandler(\Throwable $e, bool $withDie = true) { logError( get_class($e), $e->getMessage(), $e->getFile() . ':' . $e->getLine(), getExceptionTraceAsString($e) ); if($withDie){ echo $e->getTraceAsString(); throw $e; } } set_exception_handler('\\sammo\\logExceptionByCustomHandler'); function checkForFatal() { $error = error_get_last(); if($error === null){ return; } if (($error["type"]??0) == E_ERROR) { logErrorByCustomHandler($error["type"], $error["message"], $error["file"], $error["line"]); } } register_shutdown_function("\\sammo\\checkForFatal"); function getAPIExecutorClass($path) { static $basePath = __NAMESPACE__ . '\\API\\'; if (is_string($path)) { } else if (is_array($path)) { $path = join('\\', $path); } else { throw new \InvalidArgumentException("{$path}는 올바른 API 지시자가 아님"); } $classPath = str_replace('/', '\\', $basePath . $path); if (class_exists($classPath)) { return $classPath; } throw new \InvalidArgumentException("{$path}는 올바른 API 경로가 아님"); } function buildAPIExecutorClass($type, string $rootPath, array $args): \sammo\BaseAPI { $class = getAPIExecutorClass($type); return new $class($rootPath, $args); }