Claude Code Plugins

Community-maintained marketplace

Feedback

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.

Install Skill

1Download skill
2Enable skills in Claude

Open claude.ai/settings/capabilities and find the "Skills" section

3Upload to Claude

Click "Upload skill" and select the downloaded ZIP file

Note: Please verify skill by going through its instructions before using it.

SKILL.md

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
/**
 * WordPress debugging configuration.
 * Place these BEFORE "That's all, stop editing!" line.
 */

// ======================
// DEVELOPMENT ENVIRONMENT
// ======================

// Enable debug mode
define( 'WP_DEBUG', true );

// Log errors to wp-content/debug.log
define( 'WP_DEBUG_LOG', true );

// Display errors on screen (disable in production!)
define( 'WP_DEBUG_DISPLAY', true );

// Use dev versions of core JS and CSS (non-minified)
define( 'SCRIPT_DEBUG', true );

// Save database queries for analysis
define( 'SAVEQUERIES', true );

// Disable concatenation of admin scripts
define( 'CONCATENATE_SCRIPTS', false );

// ======================
// PRODUCTION ENVIRONMENT
// ======================

/*
define( 'WP_DEBUG', false );
define( 'WP_DEBUG_LOG', false );
define( 'WP_DEBUG_DISPLAY', false );
define( 'SCRIPT_DEBUG', false );
*/

// ======================
// CUSTOM LOG FILE LOCATION
// ======================

// Log to custom location (must be writable)
define( 'WP_DEBUG_LOG', '/path/to/custom/debug.log' );

// Or in uploads directory
define( 'WP_DEBUG_LOG', WP_CONTENT_DIR . '/uploads/debug.log' );

Environment-Based Configuration

<?php
/**
 * Environment-aware wp-config.php
 * Detects local development vs production
 */

// Detect local development environment
$is_local = (
    isset( $_SERVER['HTTP_HOST'] ) && (
        strpos( $_SERVER['HTTP_HOST'], '.local' ) !== false ||
        strpos( $_SERVER['HTTP_HOST'], '.test' ) !== false ||
        strpos( $_SERVER['HTTP_HOST'], 'localhost' ) !== false ||
        $_SERVER['HTTP_HOST'] === '127.0.0.1'
    )
);

// Or use environment variable
$is_local = getenv( 'WP_ENVIRONMENT_TYPE' ) === 'local';

if ( $is_local ) {
    // Local/Development settings
    define( 'WP_DEBUG', true );
    define( 'WP_DEBUG_LOG', true );
    define( 'WP_DEBUG_DISPLAY', true );
    define( 'SCRIPT_DEBUG', true );
    define( 'SAVEQUERIES', true );
    define( 'WP_ENVIRONMENT_TYPE', 'local' );
} else {
    // Production settings
    define( 'WP_DEBUG', false );
    define( 'WP_DEBUG_LOG', true ); // Still log errors
    define( 'WP_DEBUG_DISPLAY', false );
    define( 'SCRIPT_DEBUG', false );
    define( 'WP_ENVIRONMENT_TYPE', 'production' );
}

WordPress Environment Types (5.5+)

<?php
// Set environment type (local, development, staging, production)
define( 'WP_ENVIRONMENT_TYPE', 'local' );

// Usage in code
if ( wp_get_environment_type() === 'local' ) {
    // Local development only code
}

if ( wp_get_environment_type() === 'production' ) {
    // Production only code
}

// Check if development environment
function is_development_environment() {
    return in_array( wp_get_environment_type(), array( 'local', 'development' ), true );
}

Error Logging

Custom Error Logging

<?php
/**
 * Custom error logging utility.
 *
 * @package Plugin_Name
 */

/**
 * Log message to debug.log with context.
 *
 * @param mixed  $message Message to log.
 * @param string $level   Log level (debug, info, warning, error).
 * @param array  $context Additional context data.
 */
function plugin_name_log( $message, $level = 'debug', $context = array() ) {
    // Only log if WP_DEBUG is enabled
    if ( ! defined( 'WP_DEBUG' ) || ! WP_DEBUG ) {
        return;
    }

    $timestamp = current_time( 'Y-m-d H:i:s' );
    $level     = strtoupper( $level );

    // Format message
    if ( is_array( $message ) || is_object( $message ) ) {
        $message = print_r( $message, true );
    }

    // Build log entry
    $log_entry = sprintf(
        "[%s] [%s] [Plugin Name] %s",
        $timestamp,
        $level,
        $message
    );

    // Add context if provided
    if ( ! empty( $context ) ) {
        $log_entry .= ' | Context: ' . wp_json_encode( $context );
    }

    // Add backtrace for errors
    if ( $level === 'ERROR' ) {
        $backtrace  = debug_backtrace( DEBUG_BACKTRACE_IGNORE_ARGS, 5 );
        $log_entry .= "\nBacktrace:\n";
        foreach ( $backtrace as $i => $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
/**
 * Debug logging with conditional output.
 */

class Plugin_Name_Logger {

    /**
     * Log only in development.
     */
    public static function dev( $message, $context = array() ) {
        if ( wp_get_environment_type() !== 'production' ) {
            self::log( $message, 'DEBUG', $context );
        }
    }

    /**
     * Always log (for errors).
     */
    public static function error( $message, $context = array() ) {
        self::log( $message, 'ERROR', $context );
    }

    /**
     * Log with SQL query details.
     */
    public static function query( $query, $time = null ) {
        if ( defined( 'SAVEQUERIES' ) && SAVEQUERIES ) {
            $message = sprintf( 'SQL Query (%.4fs): %s', $time, $query );
            self::log( $message, 'QUERY' );
        }
    }

    /**
     * Core logging method.
     */
    private static function log( $message, $level, $context = array() ) {
        if ( ! defined( 'WP_DEBUG_LOG' ) || ! WP_DEBUG_LOG ) {
            return;
        }

        $entry = sprintf(
            '[%s] [%s] %s',
            current_time( 'c' ),
            $level,
            is_string( $message ) ? $message : print_r( $message, true )
        );

        if ( ! empty( $context ) ) {
            $entry .= ' ' . wp_json_encode( $context );
        }

        error_log( $entry );
    }
}

// Usage
Plugin_Name_Logger::dev( 'Processing started' );
Plugin_Name_Logger::error( 'Failed to save', array( 'id' => 123 ) );

Dependency Checking

Check Required Plugins

<?php
/**
 * Plugin dependency checker.
 *
 * @package Plugin_Name
 */

class Plugin_Name_Dependencies {

    /**
     * Required plugins.
     * Format: 'plugin-folder/plugin-file.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 ) {
        ?>
        <div class="notice notice-error is-dismissible">
            <p>
                <strong><?php esc_html_e( 'Plugin Name - Missing Requirements:', 'plugin-name' ); ?></strong>
            </p>
            <ul style="list-style: disc; padding-left: 20px;">
                <?php foreach ( $errors as $error ) : ?>
                    <li><?php echo esc_html( $error ); ?></li>
                <?php endforeach; ?>
            </ul>
            <p>
                <?php esc_html_e( 'Please install and activate the required plugins.', 'plugin-name' ); ?>
            </p>
        </div>
        <?php
    }
}

// Usage in main plugin file
add_action( 'plugins_loaded', function() {
    if ( ! Plugin_Name_Dependencies::check() ) {
        return; // Don't initialize plugin if dependencies not met
    }

    // Initialize plugin
    Plugin_Name::instance();
});

Plugin Version Checking

<?php
/**
 * Check plugin version requirements.
 */

class Plugin_Name_Version_Check {

    /**
     * Required plugin versions.
     *
     * @var array
     */
    private static $required_versions = array(
        'woocommerce' => 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
/**
 * Load features based on available plugins.
 */

class Plugin_Name_Features {

    /**
     * Initialize features based on available dependencies.
     */
    public static function init() {
        // Core features (always load)
        require_once PLUGIN_NAME_PATH . 'includes/core-features.php';

        // WooCommerce integration
        if ( self::is_woocommerce_ready() ) {
            require_once PLUGIN_NAME_PATH . 'includes/woocommerce-integration.php';
            add_action( 'init', array( __CLASS__, 'init_woocommerce' ) );
        }

        // BuddyPress integration
        if ( self::is_buddypress_ready() ) {
            require_once PLUGIN_NAME_PATH . 'includes/buddypress-integration.php';
            add_action( 'bp_include', array( __CLASS__, 'init_buddypress' ) );
        }

        // Elementor widgets
        if ( self::is_elementor_ready() ) {
            add_action( 'elementor/widgets/register', array( __CLASS__, 'register_elementor_widgets' ) );
        }

        // Gutenberg blocks (check if block editor is available)
        if ( self::is_gutenberg_ready() ) {
            add_action( 'init', array( __CLASS__, 'register_blocks' ) );
        }
    }

    /**
     * Check if WooCommerce is ready.
     */
    private static function is_woocommerce_ready() {
        return class_exists( 'WooCommerce' ) && defined( 'WC_VERSION' );
    }

    /**
     * Check if BuddyPress is ready.
     */
    private static function is_buddypress_ready() {
        return function_exists( 'buddypress' ) && bp_is_active( 'members' );
    }

    /**
     * Check if Elementor is ready.
     */
    private static function is_elementor_ready() {
        return did_action( 'elementor/loaded' );
    }

    /**
     * Check if Gutenberg/block editor is available.
     */
    private static function is_gutenberg_ready() {
        return function_exists( 'register_block_type' );
    }

    // Feature initialization methods...
}

// Hook early to check dependencies
add_action( 'plugins_loaded', array( 'Plugin_Name_Features', 'init' ), 20 );

Local Development Patterns

Environment Detection

<?php
/**
 * Environment detection utilities.
 */

class Plugin_Name_Environment {

    /**
     * Detect if running on local development.
     *
     * @return bool
     */
    public static function is_local() {
        // Check WP_ENVIRONMENT_TYPE first (5.5+)
        if ( function_exists( 'wp_get_environment_type' ) ) {
            return wp_get_environment_type() === 'local';
        }

        // Check for common local development patterns
        $host = $_SERVER['HTTP_HOST'] ?? '';

        $local_patterns = array(
            '.local',
            '.test',
            '.dev',
            '.localhost',
            'localhost',
            '127.0.0.1',
            '::1',
        );

        foreach ( $local_patterns as $pattern ) {
            if ( strpos( $host, $pattern ) !== false ) {
                return true;
            }
        }

        // Check for common local development tools
        $local_tools = array(
            'C:/laragon',      // Laragon
            '/Applications/MAMP',  // MAMP
            '/Applications/Local', // Local by Flywheel
            'vagrant',             // Vagrant
        );

        foreach ( $local_tools as $tool ) {
            if ( strpos( ABSPATH, $tool ) !== false ) {
                return true;
            }
        }

        return false;
    }

    /**
     * Detect specific local development tool.
     *
     * @return string|null Tool name or null.
     */
    public static function get_local_tool() {
        if ( strpos( ABSPATH, 'Local Sites' ) !== false ) {
            return 'localwp';
        }

        if ( strpos( ABSPATH, 'laragon' ) !== false ) {
            return 'laragon';
        }

        if ( strpos( ABSPATH, 'MAMP' ) !== false ) {
            return 'mamp';
        }

        if ( strpos( ABSPATH, 'vagrant' ) !== false ) {
            return 'vagrant';
        }

        if ( defined( 'WPENGINE_ACCOUNT' ) ) {
            return 'wpengine';
        }

        if ( isset( $_SERVER['PANTHEON_ENVIRONMENT'] ) ) {
            return 'pantheon';
        }

        return null;
    }

    /**
     * Check if running on staging.
     *
     * @return bool
     */
    public static function is_staging() {
        if ( function_exists( 'wp_get_environment_type' ) ) {
            return wp_get_environment_type() === 'staging';
        }

        $host = $_SERVER['HTTP_HOST'] ?? '';

        $staging_patterns = array(
            'staging.',
            'stage.',
            '.staging',
            '-staging',
            'dev.',
            '.dev',
        );

        foreach ( $staging_patterns as $pattern ) {
            if ( strpos( $host, $pattern ) !== false ) {
                return true;
            }
        }

        return false;
    }

    /**
     * Check if running on production.
     *
     * @return bool
     */
    public static function is_production() {
        if ( function_exists( 'wp_get_environment_type' ) ) {
            return wp_get_environment_type() === 'production';
        }

        return ! self::is_local() && ! self::is_staging();
    }

    /**
     * Get environment name.
     *
     * @return string
     */
    public static function get_environment() {
        if ( function_exists( 'wp_get_environment_type' ) ) {
            return wp_get_environment_type();
        }

        if ( self::is_local() ) {
            return 'local';
        }

        if ( self::is_staging() ) {
            return 'staging';
        }

        return 'production';
    }
}

// Usage examples
if ( Plugin_Name_Environment::is_local() ) {
    // Enable verbose logging
    define( 'PLUGIN_NAME_DEBUG', true );
}

if ( Plugin_Name_Environment::is_production() ) {
    // Disable debug features
}

Local WP Configuration

<?php
/**
 * Local by Flywheel specific configurations.
 */

// Detect Local WP
if ( strpos( ABSPATH, 'Local Sites' ) !== false ) {

    // Enable debug features
    define( 'WP_DEBUG', true );
    define( 'WP_DEBUG_LOG', true );
    define( 'WP_DEBUG_DISPLAY', true );
    define( 'SCRIPT_DEBUG', true );
    define( 'SAVEQUERIES', true );

    // Disable external HTTP for faster local development
    // define( 'WP_HTTP_BLOCK_EXTERNAL', true );
    // define( 'WP_ACCESSIBLE_HOSTS', 'api.wordpress.org,*.github.com' );

    // Increase memory for development
    define( 'WP_MEMORY_LIMIT', '512M' );
    define( 'WP_MAX_MEMORY_LIMIT', '512M' );

    // Disable cron for local (run manually)
    // define( 'DISABLE_WP_CRON', true );

    // Use local SSL
    // define( 'FORCE_SSL_ADMIN', false );
}

Debugging Tools

Query Monitor Integration

<?php
/**
 * Query Monitor integration for debugging.
 */

class Plugin_Name_Query_Monitor {

    /**
     * Add custom panels/data to Query Monitor.
     */
    public static function init() {
        // Only if Query Monitor is active
        if ( ! class_exists( 'QM' ) ) {
            return;
        }

        // Add custom timer
        add_action( 'plugins_loaded', array( __CLASS__, 'start_timer' ), 1 );
        add_action( 'wp_loaded', array( __CLASS__, 'end_timer' ) );

        // Log custom data
        add_filter( 'qm/output/panel', array( __CLASS__, 'add_custom_panel' ), 10, 2 );
    }

    /**
     * Start performance timer.
     */
    public static function start_timer() {
        do_action( 'qm/start', 'plugin_name_init' );
    }

    /**
     * End performance timer.
     */
    public static function end_timer() {
        do_action( 'qm/stop', 'plugin_name_init' );
    }

    /**
     * Log debug data to Query Monitor.
     *
     * @param string $message Message to log.
     * @param mixed  $data    Data to log.
     */
    public static function log( $message, $data = null ) {
        if ( function_exists( 'do_action' ) ) {
            do_action( 'qm/debug', $message, $data );
        }
    }

    /**
     * Log warning to Query Monitor.
     */
    public static function warning( $message ) {
        do_action( 'qm/warning', $message );
    }

    /**
     * Log error to Query Monitor.
     */
    public static function error( $message ) {
        do_action( 'qm/error', $message );
    }
}

// Usage
Plugin_Name_Query_Monitor::log( 'Processing order', $order_data );
Plugin_Name_Query_Monitor::warning( 'Deprecated function called' );
Plugin_Name_Query_Monitor::error( 'Failed to connect to API' );

Debug Bar Integration

<?php
/**
 * Debug Bar panel for plugin.
 */

class Plugin_Name_Debug_Bar_Panel extends Debug_Bar_Panel {

    public function init() {
        $this->title( 'Plugin Name' );
    }

    public function prerender() {
        $this->set_visible( true );
    }

    public function render() {
        $data = Plugin_Name::get_debug_data();
        ?>
        <div id="debug-bar-plugin-name">
            <h3>Plugin Name Debug Info</h3>

            <h4>Settings</h4>
            <pre><?php print_r( get_option( 'plugin_name_settings' ) ); ?></pre>

            <h4>Active Features</h4>
            <ul>
                <?php foreach ( $data['features'] as $feature => $active ) : ?>
                    <li>
                        <?php echo esc_html( $feature ); ?>:
                        <?php echo $active ? '✅' : '❌'; ?>
                    </li>
                <?php endforeach; ?>
            </ul>

            <h4>Performance</h4>
            <table>
                <tr>
                    <td>Queries:</td>
                    <td><?php echo esc_html( $data['query_count'] ); ?></td>
                </tr>
                <tr>
                    <td>Load Time:</td>
                    <td><?php echo esc_html( $data['load_time'] ); ?>ms</td>
                </tr>
            </table>
        </div>
        <?php
    }
}

// Register panel
add_filter( 'debug_bar_panels', function( $panels ) {
    if ( class_exists( 'Plugin_Name_Debug_Bar_Panel' ) ) {
        $panels[] = new Plugin_Name_Debug_Bar_Panel();
    }
    return $panels;
});

Custom Debug Helper

<?php
/**
 * Debug helper function for development.
 */

if ( ! function_exists( 'dd' ) ) {
    /**
     * Dump and die - for debugging.
     *
     * @param mixed ...$vars Variables to dump.
     */
    function dd( ...$vars ) {
        if ( ! defined( 'WP_DEBUG' ) || ! WP_DEBUG ) {
            return;
        }

        foreach ( $vars as $var ) {
            echo '<pre style="background: #1e1e1e; color: #dcdcdc; padding: 15px; margin: 10px; border-radius: 5px; overflow: auto;">';
            var_dump( $var );
            echo '</pre>';
        }

        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 '<pre style="background: #1e1e1e; color: #dcdcdc; padding: 15px; margin: 10px; border-radius: 5px; overflow: auto;">';
            var_dump( $var );
            echo '</pre>';
        }
    }
}

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 "<script>console.log('{$label}', {$js_data});</script>";
        });

        add_action( 'admin_footer', function() use ( $js_data, $label ) {
            echo "<script>console.log('{$label}', {$js_data});</script>";
        });
    }
}

// Usage
dump( $user_data );
dd( $query_results ); // Stops execution
console_log( $ajax_response, 'API Response' );

Conflict Detection

Plugin Conflict Checker

<?php
/**
 * Plugin conflict detection and resolution.
 */

class Plugin_Name_Conflict_Checker {

    /**
     * Known conflicting plugins.
     *
     * @var array
     */
    private static $known_conflicts = array(
        'plugin-that-conflicts/plugin.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 ) {
            ?>
            <div class="notice notice-warning is-dismissible">
                <p>
                    <strong><?php esc_html_e( 'Plugin Name - Potential Conflicts Detected:', 'plugin-name' ); ?></strong>
                </p>
                <?php foreach ( $conflicts as $path => $info ) : ?>
                    <p>
                        <strong><?php echo esc_html( $info['name'] ); ?>:</strong>
                        <?php echo esc_html( $info['reason'] ); ?>
                        <br>
                        <em><?php esc_html_e( 'Resolution:', 'plugin-name' ); ?></em>
                        <?php echo esc_html( $info['resolve'] ); ?>
                    </p>
                <?php endforeach; ?>
            </div>
            <?php
        });
    }

    /**
     * Check for JavaScript conflicts.
     */
    public static function check_js_conflicts() {
        add_action( 'admin_footer', function() {
            if ( ! current_user_can( 'manage_options' ) || ! defined( 'WP_DEBUG' ) || ! WP_DEBUG ) {
                return;
            }
            ?>
            <script>
            jQuery(document).ready(function($) {
                // Check for common JS conflicts
                var conflicts = [];

                // Check if jQuery is loaded multiple times
                if (window.jQuery && window.jQuery.fn.jquery !== $.fn.jquery) {
                    conflicts.push('Multiple jQuery versions detected');
                }

                // Check for undefined required globals
                var required = ['wp', 'wpApiSettings'];
                required.forEach(function(global) {
                    if (typeof window[global] === 'undefined') {
                        conflicts.push('Missing global: ' + global);
                    }
                });

                // Log conflicts
                if (conflicts.length > 0) {
                    console.warn('[Plugin Name] Potential JS conflicts:', conflicts);
                }
            });
            </script>
            <?php
        });
    }
}

// Initialize conflict checking
add_action( 'admin_init', array( 'Plugin_Name_Conflict_Checker', 'display_conflict_notices' ) );
add_action( 'admin_init', array( 'Plugin_Name_Conflict_Checker', 'check_js_conflicts' ) );

Hook Conflict Detection

<?php
/**
 * Detect hook conflicts and priority issues.
 */

class Plugin_Name_Hook_Debug {

    /**
     * Log all hooks for a specific tag.
     *
     * @param string $tag Hook tag to inspect.
     */
    public static function inspect_hook( $tag ) {
        global $wp_filter;

        if ( ! isset( $wp_filter[ $tag ] ) ) {
            error_log( sprintf( '[Plugin Name] Hook "%s" has no callbacks', $tag ) );
            return;
        }

        $callbacks = $wp_filter[ $tag ]->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
/**
 * Debug AJAX requests.
 */

// Add debugging to AJAX handlers
add_action( 'wp_ajax_my_action', function() {
    // Log incoming request
    if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) {
        error_log( 'AJAX Request: ' . print_r( $_POST, true ) );
    }

    // Validate
    if ( ! wp_verify_nonce( $_POST['nonce'], 'my_action' ) ) {
        error_log( 'AJAX Error: Invalid nonce' );
        wp_send_json_error( 'Invalid nonce' );
    }

    // Process...
    $result = process_data( $_POST );

    // Log response
    if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) {
        error_log( 'AJAX Response: ' . print_r( $result, true ) );
    }

    wp_send_json_success( $result );
});

// JavaScript debugging
add_action( 'admin_footer', function() {
    if ( ! defined( 'WP_DEBUG' ) || ! WP_DEBUG ) {
        return;
    }
    ?>
    <script>
    (function($) {
        // Intercept all AJAX calls for debugging
        $(document).ajaxSend(function(event, jqxhr, settings) {
            console.group('AJAX Request');
            console.log('URL:', settings.url);
            console.log('Type:', settings.type);
            console.log('Data:', settings.data);
            console.groupEnd();
        });

        $(document).ajaxComplete(function(event, jqxhr, settings) {
            console.group('AJAX Response');
            console.log('URL:', settings.url);
            console.log('Status:', jqxhr.status);
            console.log('Response:', jqxhr.responseJSON || jqxhr.responseText);
            console.groupEnd();
        });

        $(document).ajaxError(function(event, jqxhr, settings, error) {
            console.error('AJAX Error:', {
                url: settings.url,
                status: jqxhr.status,
                error: error,
                response: jqxhr.responseText
            });
        });
    })(jQuery);
    </script>
    <?php
});

REST API Debugging

<?php
/**
 * Debug REST API requests.
 */

add_filter( 'rest_pre_dispatch', function( $result, $server, $request ) {
    if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) {
        error_log( sprintf(
            'REST Request: %s %s',
            $request->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
/**
 * Debug database queries.
 */

add_action( 'shutdown', function() {
    if ( ! defined( 'SAVEQUERIES' ) || ! SAVEQUERIES ) {
        return;
    }

    global $wpdb;

    // Filter to only your plugin's queries
    $plugin_queries = array_filter( $wpdb->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

# 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

# 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