Кастомная ошибка 500 WordPress: пошаговое руководство для плагинов
Введение в обработку ошибок 500 в плагинах
Ошибка 500 Internal Server Error сигнализирует о сбое на уровне сервера. В контексте WordPress плагинов её часто вызывают некорректные запросы к базе, неотловленные исключения или конфликтующие зависимости. Вместо стандартной «Белой страницы смерти» можно предоставить пользователям понятный интерфейс, а разработчикам – детальные логи.
Использование wp_die для генерации 500
Функция wp_die() – базовый механизм вывода ошибок в WordPress. По умолчанию она отправляет статус 200, поэтому для 500‑й ошибки необходимо переопределить заголовок.
Пример базового wp_die
function my_plugin_fatal_error( $message ) { // Устанавливаем HTTP‑статус 500 status_header( 500 ); // Выводим сообщение через wp_die wp_die( $message, 'Server Error', array( 'response' => 500 ) ); } // Где‑то в коде плагина if ( $critical_condition_failed ) { my_plugin_fatal_error( 'Критическая ошибка плагина. Попробуйте обновить страницу позже.' ); } Добавление заголовков и собственного шаблона
Для более гибкого оформления можно использовать параметр back_link и подключить собственный шаблон через фильтр wp_die_handler.
add_filter( 'wp_die_handler', function() { return function( $message, $title = '', $args = array() ) { // Подключаем наш шаблон error-500.php из темы if ( file_exists( get_template_directory(). '/error-500.php' ) ) { include get_template_directory(). '/error-500.php'; exit; } // Фолбэк к стандартному обработчику _default_wp_die_handler( $message, $title, $args ); }; } ); Создание пользовательской страницы ошибки 500
Отдельный шаблон позволяет оформить страницу в едином стиле сайта, добавить ссылки на поддержку и даже форму обратной связи.
Шаблон error-500.php в теме
<!DOCTYPE html> <html > <head> <meta charset=""> <title></title> <meta name="viewport" content="width=device-width, initial-scale=1"> <style> body {font-family: Arial, sans-serif; text-align: center; padding: 50px;}.logo {margin-bottom: 20px;} </style> </head> <body> <div class="logo"><?php the_custom_logo();?></div> <h1></h1> <p></p> <p><a href=""></a></p> </body> </html> Подключение через хук wp_loaded
Чтобы наш шаблон отрабатывал только в случае ошибки, регистрируем хук, который проверит статус‑код.
add_action( 'wp_loaded', function() { if ( http_response_code() === 500 &&! is_admin() ) { // Запуск кастомного обработчика ошибки status_header( 500 ); include get_template_directory(). '/error-500.php'; exit; } } ); Логирование ошибок и интеграция с мониторингом
Показывать красивую страницу – лишь часть задачи. Нужно сохранять детали ошибки для разработчиков.
Стандартный error_log и WP_DEBUG_LOG
Включите отладку в wp-config.php:
define( 'WP_DEBUG', true ); define( 'WP_DEBUG_LOG', true ); // Записывает в wp-content/debug.log Затем в месте, где происходит сбой, добавьте запись:
if ( $db_error ) { error_log( '[MyPlugin] DB error: '. $db_error->get_error_message() ); my_plugin_fatal_error( 'Внутренняя ошибка. Администраторы уведомлены.' ); } Отправка в внешние сервисы
Для продакшн‑окружений удобно использовать Sentry, Loggly или аналогичные сервисы.
function my_plugin_report_sentry( $exception ) { if ( class_exists( 'SentrySentrySdk' ) ) { SentrySentrySdk::getCurrentHub()->captureException( $exception ); } } try { // Код, который может бросить исключение } catch ( Exception $e ) { my_plugin_report_sentry( $e ); my_plugin_fatal_error( 'Неожиданная ошибка. Мы уже работаем над её исправлением.' ); } Graceful degradation: как предотвратить падения
Лучший способ избавиться от 500‑й ошибки – заранее предусмотреть сценарии отказа.
Проверка условий и fallback‑логика
Перед выполнением ресурсоёмкой операции проверяйте наличие необходимых зависимостей.
if (! class_exists( 'WooCommerce' ) ) { // Выводим безопасный вариант без интеграции echo '<p>'. __( 'Для полной работы необходим плагин WooCommerce.', 'my-plugin' ). '</p>'; return; // Прерываем дальнейшее выполнение } // Основная логика плагина Пример с try/catch и WP_Error
function my_plugin_fetch_remote_data() { try { $response = wp_remote_get( 'https://api.example.com/data', array( 'timeout' => 5 ) ); if ( is_wp_error( $response ) ) { throw new Exception( $response->get_error_message() ); } $data = json_decode( wp_remote_retrieve_body( $response ), true ); if ( json_last_error()!== JSON_ERROR_NONE ) { throw new Exception( 'Invalid JSON received.' ); } return $data; } catch ( Exception $e ) { // Логируем и возвращаем WP_Error вместо фатального сбоя error_log( '[MyPlugin] Remote fetch error: '. $e->getMessage() ); return new WP_Error( 'remote_fetch_failed', __( 'Не удалось получить данные с внешнего сервера.', 'my-plugin' ) ); } } $result = my_plugin_fetch_remote_data(); if ( is_wp_error( $result ) ) { echo '<p>'. esc_html( $result->get_error_message() ). '</p>'; // Осуществляем graceful degradation, например, показываем кэш } Тестирование и отладка кастомной ошибки 500
После реализации необходимо убедиться, что ошибка отрабатывает в разных сценариях.
Инструменты и методы
- Плагин Varnish WordPress кэширование – проверка, как кэш реагирует на 500‑й статус.
- Сервис Bot Mitigation WordPress – имитирует запросы от ботов, вызывающих сбои.
- Тесты
WP_UnitTestCaseс методомsetExpectedException()для проверки выброса исключений.
Для локального тестирования используйте WP-CLI:
wp eval 'my_plugin_fatal_error("Тестовая ошибка 500");' Убедитесь, что сервер действительно возвращает код 500 (curl -I или браузер DevTools).
Заключение
Кастомная ошибка 500 в WordPress плагинах – мощный инструмент улучшения UX и ускорения диагностики. С помощью wp_die, собственного шаблона, централизованного логирования и graceful degradation вы превращаете потенциальный краш в контролируемый процесс. Не забывайте тестировать под нагрузкой и интегрировать мониторинг, чтобы своевременно реагировать на реальные инциденты.
Дополнительные ресурсы: защита WordPress от атак на REST API, GeoDNS WordPress, resource hints и OWASP Core Rule Set в WAF.
📚 Читайте также:
❓ Часто задаваемые вопросы
Как изменить HTTP‑статус, возвращаемый <code>wp_die</code>?
Перед вызовом wp_die установите заголовок через status_header(500) и передайте параметр 'response' => 500 в массив аргументов.
Где разместить шаблон пользовательской ошибки 500?
Лучше всего хранить файл error-500.php в корне активной темы. WordPress автоматически подключит его, если вы переопределите хук wp_die_handler.
Можно ли отправлять детали ошибки в сторонний сервис?
Да, в блоке catch вызовите SDK нужного сервиса (например, Sentry) и передайте объект Exception. После этого покажите пользователю общее сообщение.
Как избежать полной остановки сайта при ошибке плагина?
Используйте проверку условий и возвращайте WP_Error вместо фатального исключения. Это позволяет вывести резервный контент и сохранить работу сайта.