3v4l.org

run code in 300+ PHP versions simultaneously
<?php class ExceptionFormatter { /** @var \Exception|\Throwable */ private $exception; /** @var string */ private $formattedString; /** * @param \Exception|\Throwable $exception */ private function __construct($exception) { $this->exception = $exception; $this->formattedString = $this->formatException(); } private function formatException() { return $this->formatExceptionMessage() .$this->formatExceptionTrace() .$this->getCauseIfApplicable(); } private function formatExceptionMessage() { $exceptionClass = get_class($this->exception); $exceptionMessage = $this->exception->getMessage(); $fileAndLine = $this->formatFileAndLine($this->exception->getFile(), $this->exception->getLine()); if ($exceptionMessage === '') return "${exceptionClass} (${fileAndLine})\n"; return "${exceptionClass}: ${exceptionMessage} (${fileAndLine})\n"; } private function formatFileAndLine($file, $line) { return "${file}:${line}"; } private function formatExceptionTrace() { $exceptionTrace = $this->exception->getTrace(); $formattedTrace = []; foreach($exceptionTrace as $trace) { $formattedTrace[] = "\tat ".$this->formatTraceElement($trace); } return implode("\n", $formattedTrace); } private function formatTraceElement($traceElement) { $fileAndLine = $this->formatFileAndLine( isset($traceElement['file']) ? $traceElement['file'] : 'unknown', isset($traceElement['line']) ? $traceElement['line'] : 'unknown' ); if ($this->isFunctionCall($traceElement)) { $functionCall = $this->formatFunctionCall($traceElement); $arguments = $this->formatArguments($traceElement); return "${functionCall}(${arguments}) (${fileAndLine})"; } return $fileAndLine; } private function isFunctionCall($traceElement) { return array_key_exists('function', $traceElement); } private function formatFunctionCall($traceElement) { return (isset($traceElement['class']) ? $traceElement['class'] : '') .(isset($traceElement['type']) ? $traceElement['type'] : '') .$traceElement['function']; } private function formatArguments($traceElement) { /** @var string[] $arguments */ $arguments = $traceElement['args']; $formattedArgs = []; foreach ($arguments as $arg) { $formattedArgs[] = $this->formatArgument($arg); } return implode(', ', $formattedArgs); } private function formatArgument($arg) { if (is_string($arg)) { return "\"".$arg."\""; } else if (is_array($arg)) { return 'Array'; } else if ($arg === null) { return 'null'; } else if (is_bool($arg)) { return $arg ? 'true' : 'false'; } else if (is_object($arg)) { return get_class($arg); } else if (is_resource($arg)) { return get_resource_type($arg); } else { return $arg; } } private function getCauseIfApplicable() { $previousException = $this->exception->getPrevious(); if ($previousException !== null) return "\nCaused by: " . self::format($previousException); return ''; } /** * Converts an Exception to a Java-style stack trace string. * * @param \Exception|\Throwable The Exception/Throwable to format as a "pretty" string. * @return string */ public static function format($exception) { $formatter = new ExceptionFormatter($exception); return $formatter->getFormattedString(); } public function getFormattedString() { return $this->formattedString; } } function throwCause() { throw new RuntimeException('This is the cause'); } function nestedFunction() { try { throwCause(); } catch (Exception $e) { throw new LogicException('Lulz!', -1, $e); } } function throwExceptionForLulz($a, $b, $c, $d, ...$e) { nestedFunction(); } try { throwExceptionForLulz(['a', 'c'], "String", new stdClass(), false, 'a', 'b'); } catch (Exception $e) { echo ExceptionFormatter::format($e); }
Output for 8.2.0 - 8.2.29, 8.3.0 - 8.3.27, 8.4.1 - 8.4.14
Deprecated: Using ${var} in strings is deprecated, use {$var} instead in /in/WNLbO on line 37 Deprecated: Using ${var} in strings is deprecated, use {$var} instead in /in/WNLbO on line 37 Deprecated: Using ${var} in strings is deprecated, use {$var} instead in /in/WNLbO on line 39 Deprecated: Using ${var} in strings is deprecated, use {$var} instead in /in/WNLbO on line 39 Deprecated: Using ${var} in strings is deprecated, use {$var} instead in /in/WNLbO on line 39 Deprecated: Using ${var} in strings is deprecated, use {$var} instead in /in/WNLbO on line 44 Deprecated: Using ${var} in strings is deprecated, use {$var} instead in /in/WNLbO on line 44 Deprecated: Using ${var} in strings is deprecated, use {$var} instead in /in/WNLbO on line 71 Deprecated: Using ${var} in strings is deprecated, use {$var} instead in /in/WNLbO on line 71 Deprecated: Using ${var} in strings is deprecated, use {$var} instead in /in/WNLbO on line 71 LogicException: Lulz! (/in/WNLbO:158) at nestedFunction() (/in/WNLbO:164) at throwExceptionForLulz(Array, "String", stdClass, false, "a", "b") (/in/WNLbO:168) Caused by: RuntimeException: This is the cause (/in/WNLbO:150) at throwCause() (/in/WNLbO:156) at nestedFunction() (/in/WNLbO:164) at throwExceptionForLulz(Array, "String", stdClass, false, "a", "b") (/in/WNLbO:168)
Output for 5.6.0 - 5.6.40, 7.0.0 - 7.0.33, 7.1.0 - 7.1.33, 7.2.0 - 7.2.34, 7.3.0 - 7.3.33, 7.4.0 - 7.4.33, 8.0.0 - 8.0.30, 8.1.0 - 8.1.33
LogicException: Lulz! (/in/WNLbO:158) at nestedFunction() (/in/WNLbO:164) at throwExceptionForLulz(Array, "String", stdClass, false, "a", "b") (/in/WNLbO:168) Caused by: RuntimeException: This is the cause (/in/WNLbO:150) at throwCause() (/in/WNLbO:156) at nestedFunction() (/in/WNLbO:164) at throwExceptionForLulz(Array, "String", stdClass, false, "a", "b") (/in/WNLbO:168)

preferences:
143.57 ms | 411 KiB | 5 Q