Contents
Introduction
This article explains everything about using WP_DEBUG and WP_DEBUG_LOG to debug WordPress sites in PHP. It covers what the constants do, how to enable them safely, example usage, advanced logging techniques, reading and rotating logs, permissions, common pitfalls, and best practices for development and production environments.
What these constants do (at a glance)
WP_DEBUG | Master switch. When true, WordPress will display PHP notices, warnings, and deprecated function notices (depending on other settings). Should be enabled in development only. |
WP_DEBUG_LOG | When true, PHP notices, warnings, and errors are written to wp-content/debug.log. Can also be set to a file path to write to a custom file (use absolute path). |
WP_DEBUG_DISPLAY | Controls whether debug messages are displayed to the screen. Often set to false in combination with WP_DEBUG_LOG to keep errors off the frontend. |
SCRIPT_DEBUG | When true, WordPress will load non-minified CSS/JS (useful when debugging scripts). |
SAVEQUERIES | When true, stores database queries in memory in wpdb->queries for later inspection. Use with caution — memory overhead increases. |
Where to set these constants
Always set WP_DEBUG and related constants in wp-config.php, before the line that includes wp-settings.php. That ensures WP reads the values early. Example placement is typically right above the / Thats all, stop editing! Happy blogging. / or right after the database constants.
Basic wp-config.php example
lt?php // ... database constants above // Enable debugging for development define(WP_DEBUG, true) // Enable debugging mode define(WP_DEBUG_LOG, true) // Log to wp-content/debug.log define(WP_DEBUG_DISPLAY, false) // Dont show errors on-screen (recommended) @ini_set(display_errors, 0) // Optional useful constants define(SCRIPT_DEBUG, true) // Load non-minified scripts define(SAVEQUERIES, true) // Record database queries (slow)
Safer, environment-aware configuration
Dont leave WP_DEBUG enabled on production. Use environment variables or a WP_ENV constant to toggle debug mode. Common approaches: check an environment variable, check for a local file, or use server environment.
Example: use WP_ENV or getenv()
lt?php // Determine environment (set WP_ENV via server, .env, or other means) env = getenv(WP_ENV) ?: production if (env === development) { define(WP_DEBUG, true) define(WP_DEBUG_LOG, true) define(WP_DEBUG_DISPLAY, true) // allow on local, but false on shared dev @ini_set(display_errors, 1) } else { define(WP_DEBUG, false) define(WP_DEBUG_LOG, false) define(WP_DEBUG_DISPLAY, false) @ini_set(display_errors, 0) }
Default logfile location and custom log files
By default WP_DEBUG_LOG writes to wp-content/debug.log. You can also set WP_DEBUG_LOG to a custom absolute path (string) to write logs elsewhere. Using a custom path can help separate logs or store them outside the webroot.
Default (wp-content/debug.log)
define(WP_DEBUG, true) define(WP_DEBUG_LOG, true) // writes to WP_CONTENT_DIR . /debug.log define(WP_DEBUG_DISPLAY, false)
Custom logfile path
define(WP_DEBUG, true) define(WP_DEBUG_LOG, /var/log/my-site-wordpress-debug.log) // absolute path define(WP_DEBUG_DISPLAY, false)
If you set a custom path, ensure the web server user has write permissions to that location.
Common ways to log information in PHP/WordPress
- Use PHP error_log: error_log(message) or error_log(print_r(var, true))
- Use trigger_error: trigger_error(Something broke, E_USER_NOTICE)
- Dump variables for log: error_log(var_export(var, true)) or error_log(print_r(var, true))
- Log SQL queries: define(SAVEQUERIES, true) then inspect wpdb->queries.
- WP_ functions: _deprecated_function(_old, 1.2, _new) will trigger deprecation warnings when WP_DEBUG is on.
Examples: writing to the debug log
// Log a simple message error_log(My plugin reached this point.) // Log a variable or array my_data = array(a =gt 1, b =gt 2) error_log(print_r(my_data, true)) // Trigger a PHP user notice (shows in the log) trigger_error(User-level notice: invalid input, E_USER_NOTICE)
Debugging AJAX, REST API, and CLI requests
WP_DEBUG and WP_DEBUG_LOG apply to front-end, admin, AJAX, REST, and CLI runs, as long as the constants are defined. For AJAX and REST, keep WP_DEBUG_DISPLAY false (or errors may break JSON responses) and rely on logging instead.
AJAX example (admin-ajax.php)
add_action(wp_ajax_my_action, function() { data = _POST[data] ?? null if (!data) { error_log(AJAX my_action received no data: . print_r(_POST, true)) wp_send_json_error(Missing data) } // ... handling ... wp_send_json_success([ok =gt true]) })
Inspecting database queries
Enable SAVEQUERIES to capture queries in wpdb->queries (array). This is useful for pinpointing slow queries or debugging excessive queries. Only enable in development because it stores queries in memory.
define(SAVEQUERIES, true) define(WP_DEBUG, true) define(WP_DEBUG_LOG, true) define(WP_DEBUG_DISPLAY, false) // Later in code (after queries run) global wpdb error_log(Queries: . print_r(wpdb->queries, true))
File permissions and ownership
If debug.log is not created or you get permission errors, confirm the following:
- The wp-content directory is writable by the web server user (www-data, apache, nginx, etc.).
- Typical permissions: directories 755, files 644. The owner should be the web server user or a group that includes it.
- If using a custom log path, adjust ownership/permissions for that path accordingly.
Example permission commands (Linux)
# Set ownership to web server user (example: www-data) sudo chown -R www-data:www-data /var/www/site # Ensure directories are 755 and files 644 sudo find /var/www/site -type d -exec chmod 755 {} sudo find /var/www/site -type f -exec chmod 644 {}
Viewing and monitoring logs
- tail -f on Linux/macOS: tail -f wp-content/debug.log
- less: less F wp-content/debug.log
- PowerShell on Windows: Get-Content debug.log -Wait
- When using a custom file, substitute its path.
# Real-time view on Linux/macOS tail -f /var/www/site/wp-content/debug.log
Log rotation and size management
Debug logs can grow large. On server environments, use logrotate or other rotation tools. Basic logrotate snippet:
/var/www/site/wp-content/debug.log { daily rotate 14 compress missingok notifempty create 644 www-data www-data }
Adjust ownership and rotation frequency based on your needs.
Advanced: custom logging and third-party libraries
For complex projects, consider using a PSR-3 logger like Monolog and writing logs to syslog, a cloud service, or a location outside the webroot. Example: instantiate Monolog and push messages to a rotating file handler instead of relying solely on WP_DEBUG_LOG.
Basic Monolog usage (concept)
use MonologLogger use MonologHandlerRotatingFileHandler log = new Logger(my-site) handler = new RotatingFileHandler(/var/log/my-site/my-app.log, 7) log->pushHandler(handler) log->info(Starting process, [context =gt context])
You can still use WP_DEBUG to surface WP notices while using Monolog for structured application logging.
Interpreting messages in debug.log
- Notices/Warnigns: Often indicate undefined variables, incorrect arguments, or use of deprecated functions.
- Deprecated: Signals functions or arguments that will be removed in future WP versions. Update code accordingly.
- Fatal errors: Stop execution check stack traces and file paths indicated in the log. Fix cause (missing function, fatal call) or disable a plugin/theme until resolved.
Common pitfalls and troubleshooting
- WP_DEBUG defined too late: If you define constants after WP has bootstrapped, they may not take effect. Always place them in wp-config.php before require_once ABSPATH . wp-settings.php.
- display_errors conflict: PHPs display_errors ini setting may override WP_DEBUG_DISPLAY. Use @ini_set(display_errors, 0) to be explicit when you dont want screen output.
- Production enabled by mistake: Leaving WP_DEBUG true on production can leak sensitive paths and data. Verify environment configuration and restrict access to debug logs.
- Permissions issues: debug.log not created because the web server user cannot write to wp-content. Fix ownership/permissions.
- JSON/API responses broken: Showing PHP notices in API responses can break JSON structure. Use WP_DEBUG_DISPLAY = false and review logs instead.
Debugging with Xdebug and step debugging
The WP_DEBUG constants control PHP/WordPress behavior but do not provide step debugging. For breakpoints, stack inspection, and step-through debugging, install Xdebug and configure your IDE (VS Code, PHPStorm). Use Xdebug for development and disable it in production.
- Set xdebug.mode=develop,debug in php.ini (Xdebug 3).
- Use xdebug.start_with_request=yes or trigger cookies to begin a remote session.
- Combine Xdebug (step debugging) with WP_DEBUG for the best inspection workflow.
Using WP-CLI to change configuration
WP-CLI can modify wp-config.php or set environment-specific settings. Example:
# Set WP_DEBUG in wp-config.php (writes a raw boolean) wp config set WP_DEBUG true --raw wp config set WP_DEBUG_LOG true --raw wp config set WP_DEBUG_DISPLAY false --raw
Examples of real-world debugging patterns
1) Logging during plugin initialization
add_action(plugins_loaded, function() { if (defined(WP_DEBUG) WP_DEBUG) { error_log(MyPlugin: plugins_loaded fired) } })
2) Conditional logging only for certain users
add_action(init, function() { if (defined(WP_DEBUG) WP_DEBUG current_user_can(manage_options)) { error_log(Admin accessed init, user ID: . get_current_user_id()) } })
3) Capturing PHP shutdown errors (fatal errors)
register_shutdown_function(function() { err = error_get_last() if (err !== null) { error_log(Shutdown error: . print_r(err, true)) } })
Security and privacy considerations
- Never expose debug logs publicly. Keep debug.log outside of web-accessible directories or protect via server config.
- Logs may contain sensitive data (API keys, user data) avoid logging secrets and sanitize before logging.
- Turn off WP_DEBUG and WP_DEBUG_LOG in production unless you have a controlled, secure logging solution.
Troubleshooting checklist
- Confirm WP_DEBUG constants are set in wp-config.php and before wp-settings.php is loaded.
- Check WP_DEBUG_LOG file existence and permissions.
- Set WP_DEBUG_DISPLAY to false if output breaks pages or JSON.
- Use error_log(print_r(…, true)) to log complex data structures.
- Use SAVEQUERIES to inspect SQL queries when investigating performance issues.
- Use Xdebug for step-by-step diagnostics for complex bugs.
References and further reading
Summary
WP_DEBUG and WP_DEBUG_LOG are powerful tools for finding PHP notices, warnings, deprecations, and runtime errors in WordPress. Use them in development with WP_DEBUG_DISPLAY off on shared environments, log to files, monitor permissions, rotate logs, and never leave verbose debugging enabled on production. Combine WP_DEBUG with targeted error_log statements, SAVEQUERIES, and Xdebug for thorough debugging workflows.
|
Acepto donaciones de BAT's mediante el navegador Brave 🙂 |