--- name: wp-debugging description: WordPress debugging, dependency checking, and local development patterns. Use when debugging WordPress issues, checking plugin dependencies, setting up local environments, resolving conflicts, or troubleshooting errors in themes and plugins. --- # WordPress Debugging & Dependency Management Comprehensive debugging techniques, dependency checking, local development patterns, and conflict resolution for WordPress themes and plugins. ## When to Use **Use when:** - Debugging PHP errors, warnings, notices - Checking if required plugins are active - Setting up local development environments - Resolving plugin/theme conflicts - Troubleshooting performance issues - Setting up wp-config.php debug options - Using Query Monitor, Debug Bar, or other tools --- ## Debug Mode Configuration ### wp-config.php Debug Settings ```php $trace ) { $log_entry .= sprintf( " #%d %s:%d %s()\n", $i, $trace['file'] ?? 'unknown', $trace['line'] ?? 0, $trace['function'] ?? 'unknown' ); } } error_log( $log_entry ); } // Usage examples plugin_name_log( 'Plugin initialized' ); plugin_name_log( 'User action', 'info', array( 'user_id' => 123 ) ); plugin_name_log( $user_data, 'debug' ); // Arrays/objects plugin_name_log( 'Something went wrong', 'error' ); // Includes backtrace ``` ### Conditional Logging ```php 123 ) ); ``` --- ## Dependency Checking ### Check Required Plugins ```php 'Display Name' * * @var array */ private static $required_plugins = array( 'woocommerce/woocommerce.php' => 'WooCommerce', 'advanced-custom-fields/acf.php' => 'Advanced Custom Fields', 'buddypress/bp-loader.php' => 'BuddyPress', ); /** * Optional plugins (enhanced features). * * @var array */ private static $optional_plugins = array( 'query-monitor/query-monitor.php' => 'Query Monitor', ); /** * Minimum PHP version. * * @var string */ private static $min_php_version = '8.0'; /** * Minimum WordPress version. * * @var string */ private static $min_wp_version = '6.0'; /** * Check all dependencies. * * @return bool True if all dependencies met. */ public static function check() { $errors = array(); // Check PHP version if ( version_compare( PHP_VERSION, self::$min_php_version, '<' ) ) { $errors[] = sprintf( /* translators: 1: Required PHP version, 2: Current PHP version */ __( 'PHP %1$s or higher is required. You are running PHP %2$s.', 'plugin-name' ), self::$min_php_version, PHP_VERSION ); } // Check WordPress version if ( version_compare( get_bloginfo( 'version' ), self::$min_wp_version, '<' ) ) { $errors[] = sprintf( /* translators: 1: Required WP version, 2: Current WP version */ __( 'WordPress %1$s or higher is required. You are running WordPress %2$s.', 'plugin-name' ), self::$min_wp_version, get_bloginfo( 'version' ) ); } // Check required plugins $missing_plugins = self::get_missing_plugins(); if ( ! empty( $missing_plugins ) ) { $errors[] = sprintf( /* translators: %s: List of missing plugins */ __( 'The following required plugins are missing or inactive: %s', 'plugin-name' ), implode( ', ', $missing_plugins ) ); } if ( ! empty( $errors ) ) { add_action( 'admin_notices', function() use ( $errors ) { self::display_admin_notice( $errors ); }); return false; } return true; } /** * Get list of missing required plugins. * * @return array Missing plugin names. */ public static function get_missing_plugins() { if ( ! function_exists( 'is_plugin_active' ) ) { require_once ABSPATH . 'wp-admin/includes/plugin.php'; } $missing = array(); foreach ( self::$required_plugins as $plugin_path => $plugin_name ) { if ( ! is_plugin_active( $plugin_path ) ) { $missing[] = $plugin_name; } } return $missing; } /** * Check if a specific plugin is active. * * @param string $plugin_path Plugin path (e.g., 'woocommerce/woocommerce.php'). * @return bool */ public static function is_plugin_active( $plugin_path ) { if ( ! function_exists( 'is_plugin_active' ) ) { require_once ABSPATH . 'wp-admin/includes/plugin.php'; } return is_plugin_active( $plugin_path ); } /** * Check if WooCommerce is active. * * @return bool */ public static function is_woocommerce_active() { return self::is_plugin_active( 'woocommerce/woocommerce.php' ); } /** * Check if BuddyPress is active. * * @return bool */ public static function is_buddypress_active() { return self::is_plugin_active( 'buddypress/bp-loader.php' ) || function_exists( 'buddypress' ); } /** * Check if ACF is active. * * @return bool */ public static function is_acf_active() { return self::is_plugin_active( 'advanced-custom-fields/acf.php' ) || self::is_plugin_active( 'advanced-custom-fields-pro/acf.php' ) || class_exists( 'ACF' ); } /** * Check if Elementor is active. * * @return bool */ public static function is_elementor_active() { return defined( 'ELEMENTOR_VERSION' ); } /** * Display admin notice for missing dependencies. * * @param array $errors Error messages. */ private static function display_admin_notice( $errors ) { ?>

array( 'path' => 'woocommerce/woocommerce.php', 'name' => 'WooCommerce', 'version' => '8.0.0', 'constant' => 'WC_VERSION', ), 'elementor' => array( 'path' => 'elementor/elementor.php', 'name' => 'Elementor', 'version' => '3.18.0', 'constant' => 'ELEMENTOR_VERSION', ), 'buddypress' => array( 'path' => 'buddypress/bp-loader.php', 'name' => 'BuddyPress', 'version' => '12.0.0', 'function' => 'bp_get_version', ), ); /** * Check if plugin meets version requirement. * * @param string $plugin Plugin key from $required_versions. * @return bool|string True if met, error message if not. */ public static function check_version( $plugin ) { if ( ! isset( self::$required_versions[ $plugin ] ) ) { return true; } $config = self::$required_versions[ $plugin ]; // Check if plugin is active if ( ! function_exists( 'is_plugin_active' ) ) { require_once ABSPATH . 'wp-admin/includes/plugin.php'; } if ( ! is_plugin_active( $config['path'] ) ) { return sprintf( '%s is not active.', $config['name'] ); } // Get current version $current_version = null; if ( isset( $config['constant'] ) && defined( $config['constant'] ) ) { $current_version = constant( $config['constant'] ); } elseif ( isset( $config['function'] ) && function_exists( $config['function'] ) ) { $current_version = call_user_func( $config['function'] ); } if ( ! $current_version ) { return true; // Can't determine version, assume OK } // Compare versions if ( version_compare( $current_version, $config['version'], '<' ) ) { return sprintf( '%s version %s or higher is required. You have version %s.', $config['name'], $config['version'], $current_version ); } return true; } /** * Check all required versions. * * @return array Errors array (empty if all OK). */ public static function check_all() { $errors = array(); foreach ( array_keys( self::$required_versions ) as $plugin ) { $result = self::check_version( $plugin ); if ( true !== $result ) { $errors[] = $result; } } return $errors; } } // Usage $version_errors = Plugin_Name_Version_Check::check_all(); if ( ! empty( $version_errors ) ) { // Display admin notice with errors } ``` ### Conditional Feature Loading ```php title( 'Plugin Name' ); } public function prerender() { $this->set_visible( true ); } public function render() { $data = Plugin_Name::get_debug_data(); ?>

Plugin Name Debug Info

Settings

Active Features

Performance

Queries:
Load Time: ms
'; var_dump( $var ); echo ''; } die(); } } if ( ! function_exists( 'dump' ) ) { /** * Dump without dying. * * @param mixed ...$vars Variables to dump. */ function dump( ...$vars ) { if ( ! defined( 'WP_DEBUG' ) || ! WP_DEBUG ) { return; } foreach ( $vars as $var ) { echo '
';
            var_dump( $var );
            echo '
'; } } } if ( ! function_exists( 'console_log' ) ) { /** * Log to browser console. * * @param mixed $data Data to log. * @param string $label Optional label. */ function console_log( $data, $label = '' ) { if ( ! defined( 'WP_DEBUG' ) || ! WP_DEBUG ) { return; } $js_data = wp_json_encode( $data ); $label = esc_js( $label ); add_action( 'wp_footer', function() use ( $js_data, $label ) { echo ""; }); add_action( 'admin_footer', function() use ( $js_data, $label ) { echo ""; }); } } // Usage dump( $user_data ); dd( $query_results ); // Stops execution console_log( $ajax_response, 'API Response' ); ``` --- ## Conflict Detection ### Plugin Conflict Checker ```php array( 'name' => 'Conflicting Plugin', 'reason' => 'Uses same shortcode [example]', 'resolve' => 'Deactivate one of the plugins or use the filter to change shortcode.', ), 'another-conflict/plugin.php' => array( 'name' => 'Another Plugin', 'reason' => 'Overrides same hooks with different priority', 'resolve' => 'Adjust hook priority using filters.', ), ); /** * Check for known conflicts. * * @return array Active conflicts. */ public static function check_conflicts() { if ( ! function_exists( 'is_plugin_active' ) ) { require_once ABSPATH . 'wp-admin/includes/plugin.php'; } $conflicts = array(); foreach ( self::$known_conflicts as $plugin_path => $info ) { if ( is_plugin_active( $plugin_path ) ) { $conflicts[ $plugin_path ] = $info; } } return $conflicts; } /** * Display conflict warnings in admin. */ public static function display_conflict_notices() { $conflicts = self::check_conflicts(); if ( empty( $conflicts ) ) { return; } add_action( 'admin_notices', function() use ( $conflicts ) { ?>

$info ) : ?>

:

callbacks; error_log( sprintf( '[Plugin Name] Hook "%s" callbacks:', $tag ) ); foreach ( $callbacks as $priority => $hooks ) { foreach ( $hooks as $id => $hook ) { $callback = $hook['function']; // Get callback name if ( is_array( $callback ) ) { if ( is_object( $callback[0] ) ) { $name = get_class( $callback[0] ) . '->' . $callback[1]; } else { $name = $callback[0] . '::' . $callback[1]; } } elseif ( is_string( $callback ) ) { $name = $callback; } else { $name = 'closure'; } error_log( sprintf( ' Priority %d: %s (args: %d)', $priority, $name, $hook['accepted_args'] ) ); } } } /** * Find plugins that hook into a specific action/filter. * * @param string $tag Hook tag. * @return array Plugins using this hook. */ public static function find_hook_users( $tag ) { global $wp_filter; $users = array(); if ( ! isset( $wp_filter[ $tag ] ) ) { return $users; } foreach ( $wp_filter[ $tag ]->callbacks as $priority => $hooks ) { foreach ( $hooks as $hook ) { $callback = $hook['function']; // Try to determine source if ( is_array( $callback ) && is_object( $callback[0] ) ) { $reflection = new ReflectionClass( $callback[0] ); $file = $reflection->getFileName(); } elseif ( is_array( $callback ) && is_string( $callback[0] ) ) { $reflection = new ReflectionMethod( $callback[0], $callback[1] ); $file = $reflection->getFileName(); } elseif ( is_string( $callback ) && function_exists( $callback ) ) { $reflection = new ReflectionFunction( $callback ); $file = $reflection->getFileName(); } else { continue; } // Determine if it's a plugin if ( strpos( $file, 'wp-content/plugins/' ) !== false ) { preg_match( '/wp-content\/plugins\/([^\/]+)/', $file, $matches ); if ( ! empty( $matches[1] ) ) { $users[] = array( 'plugin' => $matches[1], 'priority' => $priority, 'file' => $file, ); } } } } return $users; } } // Debug usage if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) { add_action( 'wp_loaded', function() { // Inspect hooks your plugin uses Plugin_Name_Hook_Debug::inspect_hook( 'woocommerce_checkout_process' ); }); } ``` --- ## Common Debugging Scenarios ### AJAX Debugging ```php get_method(), $request->get_route() )); error_log( 'REST Params: ' . print_r( $request->get_params(), true ) ); } return $result; }, 10, 3 ); add_filter( 'rest_post_dispatch', function( $response, $server, $request ) { if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) { error_log( sprintf( 'REST Response: %s %s - Status: %d', $request->get_method(), $request->get_route(), $response->get_status() )); } return $response; }, 10, 3 ); ``` ### Database Query Debugging ```php queries, function( $query ) { return strpos( $query[2], 'plugin_name' ) !== false || strpos( $query[0], 'plugin_name' ) !== false; }); if ( empty( $plugin_queries ) ) { return; } error_log( '=== Plugin Name Database Queries ===' ); $total_time = 0; foreach ( $plugin_queries as $query ) { error_log( sprintf( "Query: %s\nTime: %.4fs\nCaller: %s\n", $query[0], $query[1], $query[2] )); $total_time += $query[1]; } error_log( sprintf( 'Total: %d queries, %.4fs', count( $plugin_queries ), $total_time )); }); ``` --- ## Debugging Checklist ### Before Debugging - [ ] Enable WP_DEBUG in wp-config.php - [ ] Enable WP_DEBUG_LOG - [ ] Install Query Monitor plugin - [ ] Clear all caches - [ ] Disable caching plugins temporarily ### Common Issues | Issue | Likely Cause | Solution | |-------|--------------|----------| | White screen | PHP fatal error | Check debug.log | | 500 error | Server/PHP error | Check server error logs | | AJAX fails | Nonce/permission | Log AJAX data | | Styles broken | Caching | Clear cache, check priority | | Plugin conflict | Hook priority | Check hook order | | Memory exhausted | Too much data | Increase memory limit | | Timeout | Slow queries | Profile with SAVEQUERIES | ### Useful WP-CLI Commands ```bash # Check WordPress configuration wp config list # Check active plugins wp plugin list --status=active # Check for PHP errors wp eval "error_reporting(E_ALL); ini_set('display_errors', 1);" # Verify plugin dependencies wp plugin verify-checksums plugin-name # Test REST API wp rest GET /wp/v2/posts # Clear transients wp transient delete --all # Check cron events wp cron event list # Debug mode toggle wp config set WP_DEBUG true --raw wp config set WP_DEBUG_LOG true --raw ``` ### Debug Log Analysis ```bash # View recent log entries tail -f wp-content/debug.log # Search for specific errors grep -i "fatal error" wp-content/debug.log # Search for plugin-specific logs grep "Plugin Name" wp-content/debug.log # Count errors by type grep -oP '\[\w+\]' wp-content/debug.log | sort | uniq -c # Clear debug log > wp-content/debug.log ```