Why can't this be a regular plugin? Or why can't I just override these settings in php.ini instead?
This code needs to go in mu-plugins
because of some quirks of how WP Core itself overrides the error logging settings.
- If you make changes in php.ini or other server level settings, they will get overridden by WP Core
- If you put
ini_set
anderror_reporting
changes in wp-config.php - same thing - they will load before the core files that modify error logging and get overridden. - If you use a regular plugin, then all of the errors in plugins that come before this one alphabetically will fire before these settings do.
- So
mu-plugins
in the only dependable place to run this code.
Place the my-squarecandy-error-logging.php file in wp-content/mu-plugins/
Define the SQCDY_ERROR_LOG_PATH constant in your wp-config.php
- Set to false or just don't define it to use the server and WP default error log paths.
- Set to true to use our new custom default path of
../logs/{site-domain}-sqcdy-php.log
. The plugin will automatically create thelogs
directory one level up from the WordPress root if it does not exist. - Set to any custom absolute error log path if you need something other than the default.
If this option is used, it will be used instead of /wp-content/debug.log if WP_DEBUG is true, and will separate out the PHP errors from the web server error log even with WP_DEBUG off.
Nginx logs rendering of PHP errors in partciular can be quite problematic. They are often truncated, grouped together or contain misleading layers of error levels.
Example nginx log entry: (note that it includes all the keywords "error", "message" and "Warning" for a warning level error)
2025/06/26 12:12:07 [error] 997946#997946: *176601 FastCGI sent in stderr: "PHP message: PHP Warning: Undefined variable $does_not_exist in ...
Example PHP error log entry:
2025/06/26 12:12:07 PHP Warning: Undefined variable $does_not_exist in ...
With this plugin installed and no additional configuration, the default WordPress error level is set to ignore notices and deprecated errors. This will stop the logs from being filled with "doing it wrong" notices and deprecated errors that are not actually errors yet. ( _load_textdomain_just_in_time errors will be skipped )
You can override this default error level by defining the following constants in your wp-config.php:
SQCDY_DEBUG_ALL
- set to true to show all errors, including notices and deprecated errors.SQCDY_DEBUG_ERROR_LEVEL
- set to an integer value to override the error level, e.g.E_ALL
,E_ERROR
, etc.
define( 'WP_DEBUG', true ); // enable debugging
define( 'WP_DEBUG_LOG', true ); // enable debug log
define( 'WP_DEBUG_DISPLAY', false ); // disable debug display on the front-end
define( 'SQCDY_ERROR_LOG_PATH', true ); // use the default error log path
// uncomment to show all errors
// define( 'SQCDY_DEBUG_ALL', true );
// uncomment to override the error level to something custom
// define( 'SQCDY_DEBUG_ERROR_LEVEL', E_ALL ^ E_USER_NOTICE );