PHP Post-Mortem Debugger
2026 update: I originally wrote this snippet over a decade ago. While modern tools like Xdebug and framework exception handlers cover most debugging needs, this technique can still help when PHP fails before normal error handling kicks in. Admittedly, I still use it from time to time when faced with issues in old codebases.
PHP is very configurable, but sometimes default settings or those imposed by the framework in use tend to make simple debugging very difficult.
Don’t get me wrong, whenever possible a proper debugger such as Xdebug is the way to go. But sometimes, when all else fails, and you’re facing a blank white page, the snippet below can get you out of the situation in no time.
1<?php
2
3register_shutdown_function(static function () {
4 while (ob_get_level() > 0) {
5 ob_end_clean();
6 }
7 ob_implicit_flush(true);
8
9 echo "<!--\n";
10
11 echo "\n\tHeaders Sent:";
12 $file = $line = null;
13 headers_sent($file, $line);
14 $file = empty($file) ? 'unknown' : $file;
15 echo "\n\t\tat $file:$line";
16
17 echo "\n\tLast Error:";
18 $lastError = error_get_last();
19 if (!empty($lastError)) {
20 foreach (get_defined_constants(true)['Core'] as $name => $constantValue) {
21 if (substr($name, 0, 2) === 'E_' && $constantValue === $lastError['type']) {
22 $lastError['type'] = $name;
23 break;
24 }
25 }
26 echo str_replace("\n", "\n\t\t", htmlspecialchars("\n{$lastError['message']} ({$lastError['type']}) in {$lastError['file']}:{$lastError['line']}"));
27 } else {
28 echo "\n\t\tnone";
29 }
30
31 echo "\n\tIncluded Files:";
32 echo "\n\t\t" . implode("\n\t\t", get_included_files());
33
34 echo "\n-->";
35});
36
So, how does it work?
While a long time has passed since I first wrote it, little changed in the way it works.
As you might know, in PHP you can register a shutdown handler – a function to be called when PHP is closing down. What you might not know is that this function is called even when many fatal errors occur, making it useful for retrieving debugging information during otherwise unrecoverable failures.
This functionality makes it a good candidate for retrieving interesting information on the current page run, such as:
- where the initial output started from (used to diagnose corrupted output)
- last error message (useful to see fatal errors, especially when errors are hidden)
- the loaded files (useful to find which file caused PHP to stop)
All this is conveniently rendered inside an HTML comment to (hopefully) prevent anything visible from appearing in HTML responses. Of course, use this script with care, it may easily expose internal server details such as system paths.