Created
June 4, 2026 03:11
-
-
Save vapvarun/fb27c12ebb832ebd5d10d6f84a2cbcb3 to your computer and use it in GitHub Desktop.
Capture PHP fatal errors on WordPress shutdown with logging and Slack alert - tweakswp.com tutorial
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <?php | |
| /** | |
| * Capture fatal errors on WordPress shutdown | |
| * | |
| * WordPress catches many errors through WP_Error and wp_die(), but PHP-level | |
| * fatal errors (E_ERROR, E_PARSE) kill the script before any WordPress handler | |
| * can run. register_shutdown_function() is the only way to intercept them. | |
| * | |
| * Tutorial: https://tweakswp.com/ | |
| */ | |
| /** | |
| * Fatal error handler registered with PHP's shutdown mechanism. | |
| * | |
| * Writes fatal error details to a persistent log file and optionally | |
| * sends an alert to a Slack webhook. | |
| */ | |
| function tweakswp_fatal_error_handler(): void { | |
| $error = error_get_last(); | |
| if ( ! $error ) { | |
| return; | |
| } | |
| // Only act on errors that killed the script. Warnings and notices | |
| // are handled by the standard WP_DEBUG / error_log path. | |
| $fatal_types = [ E_ERROR, E_PARSE, E_CORE_ERROR, E_COMPILE_ERROR, E_USER_ERROR ]; | |
| if ( ! in_array( $error['type'], $fatal_types, true ) ) { | |
| return; | |
| } | |
| $message = sprintf( | |
| '[%s] FATAL: %s in %s:%d', | |
| gmdate( 'Y-m-d H:i:s' ), | |
| $error['message'], | |
| $error['file'], | |
| $error['line'] | |
| ); | |
| // 1. Write to a dedicated fatal log (outside the webroot if possible). | |
| $log_file = WP_CONTENT_DIR . '/fatal-errors.log'; | |
| // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_file_put_contents | |
| file_put_contents( $log_file, $message . PHP_EOL, FILE_APPEND | LOCK_EX ); | |
| // 2. Optional: POST to a Slack webhook. | |
| // Only runs if the cURL extension is loaded — no WordPress helpers available. | |
| $webhook_url = defined( 'TWEAKSWP_SLACK_WEBHOOK' ) ? TWEAKSWP_SLACK_WEBHOOK : ''; | |
| if ( $webhook_url && extension_loaded( 'curl' ) ) { | |
| $ch = curl_init( $webhook_url ); | |
| curl_setopt_array( $ch, [ | |
| CURLOPT_POST => true, | |
| CURLOPT_POSTFIELDS => json_encode( [ 'text' => $message ] ), | |
| CURLOPT_RETURNTRANSFER => true, | |
| CURLOPT_TIMEOUT => 5, | |
| CURLOPT_HTTPHEADER => [ 'Content-Type: application/json' ], | |
| ] ); | |
| curl_exec( $ch ); | |
| curl_close( $ch ); | |
| } | |
| } | |
| // Register as early as possible — ideally in an mu-plugin so it covers | |
| // fatal errors that occur before plugins finish loading. | |
| register_shutdown_function( 'tweakswp_fatal_error_handler' ); | |
| // Define the webhook URL in wp-config.php: | |
| // define( 'TWEAKSWP_SLACK_WEBHOOK', 'https://hooks.slack.com/services/YOUR/WEBHOOK/URL' ); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment