{"id":5723,"date":"2026-02-12T20:45:13","date_gmt":"2026-02-13T01:45:13","guid":{"rendered":"https:\/\/chubes.net\/?documentation=wordpress-plugin-api-overview"},"modified":"2026-03-13T03:28:51","modified_gmt":"2026-03-13T07:28:51","slug":"wordpress-plugin-api-overview","status":"publish","type":"documentation","link":"https:\/\/chubes.net\/docs\/wordpress-core\/plugins\/wordpress-plugin-api-overview\/","title":{"rendered":"WordPress Plugin API Overview"},"content":{"rendered":"<p>The Plugin API is WordPress&#8217;s system for extending core functionality through modular code packages. It encompasses plugin loading, activation lifecycle, pluggable functions, and mu-plugins.<\/p><h2 class=\"wp-block-heading\">Plugin Types<\/h2><h3 class=\"wp-block-heading\">Standard Plugins (<code>wp-content\/plugins\/<\/code>)<\/h3><ul class=\"wp-block-list\"><li>Installed in <code>WP_PLUGIN_DIR<\/code> (default: <code>wp-content\/plugins\/<\/code>)<\/li><li>Must be explicitly activated via admin or programmatically<\/li><li>Can be activated per-site or network-wide (Multisite)<\/li><li>Support activation, deactivation, and uninstall hooks<\/li><\/ul><h3 class=\"wp-block-heading\">Must-Use Plugins (<code>wp-content\/mu-plugins\/<\/code>)<\/h3><ul class=\"wp-block-list\"><li>Installed in <code>WPMU_PLUGIN_DIR<\/code> (default: <code>wp-content\/mu-plugins\/<\/code>)<\/li><li>Automatically loaded on every request<\/li><li>Cannot be deactivated through admin interface<\/li><li>No subdirectory support (only files in root are loaded)<\/li><li>Loaded before regular plugins<\/li><\/ul><h3 class=\"wp-block-heading\">Drop-ins (<code>wp-content\/<\/code>)<\/h3><ul class=\"wp-block-list\"><li>Special plugins that replace core functionality<\/li><li>Located directly in <code>WP_CONTENT_DIR<\/code><\/li><li>Examples: <code>advanced-cache.php<\/code>, <code>db.php<\/code>, <code>object-cache.php<\/code><\/li><\/ul><h2 class=\"wp-block-heading\">Plugin Loading Order<\/h2><ol class=\"wp-block-list\"><li><strong>Drop-ins<\/strong> &#8211; Loaded during WordPress initialization<\/li><li><strong>Must-Use Plugins<\/strong> &#8211; Loaded via <code>wp_get_mu_plugins()<\/code> in <code>wp-settings.php<\/code><\/li><li><strong>Active Plugins<\/strong> &#8211; Loaded from <code>active_plugins<\/code> option<\/li><\/ol><h2 class=\"wp-block-heading\">Plugin File Structure<\/h2><h3 class=\"wp-block-heading\">Header Requirements<\/h3><div class=\"code-block-wrapper\"><div class=\"code-block-header\"><span class=\"code-block-language\">php<\/span><button class=\"code-copy-btn\" aria-label=\"Copy code\"><svg><use href=\"https:\/\/chubes.net\/wp-content\/themes\/chubes\/assets\/icons\/chubes.svg#icon-copy\"><\/use><\/svg><\/button><\/div><pre data-chubes-enhanced class=\"wp-block-code language-php\"><code class=\"language-php\">\/*\nPlugin Name: My Plugin\nPlugin URI: https:\/\/example.com\/my-plugin\nDescription: A brief description of the plugin.\nVersion: 1.0.0\nAuthor: Author Name\nAuthor URI: https:\/\/example.com\nText Domain: my-plugin\nDomain Path: \/languages\nNetwork: true\nRequires at least: 6.0\nRequires PHP: 7.4\nRequires Plugins: woocommerce, jetpack\nUpdate URI: https:\/\/example.com\/updates\/\n*\/<\/code><\/pre><\/div><h3 class=\"wp-block-heading\">Header Fields<\/h3><figure class=\"wp-block-table\"><table><thead><tr><th>Field<\/th><th>Required<\/th><th>Description<\/th><\/tr><\/thead><tbody><tr><td><code>Plugin Name<\/code><\/td><td>Yes<\/td><td>Display name for the plugin<\/td><\/tr><tr><td><code>Version<\/code><\/td><td>Recommended<\/td><td>Current version number<\/td><\/tr><tr><td><code>Description<\/code><\/td><td>Recommended<\/td><td>Brief description<\/td><\/tr><tr><td><code>Author<\/code><\/td><td>Recommended<\/td><td>Plugin author name<\/td><\/tr><tr><td><code>Plugin URI<\/code><\/td><td>No<\/td><td>Plugin homepage URL<\/td><\/tr><tr><td><code>Author URI<\/code><\/td><td>No<\/td><td>Author homepage URL<\/td><\/tr><tr><td><code>Text Domain<\/code><\/td><td>No<\/td><td>Translation text domain<\/td><\/tr><tr><td><code>Domain Path<\/code><\/td><td>No<\/td><td>Path to translation files<\/td><\/tr><tr><td><code>Network<\/code><\/td><td>No<\/td><td>Require network-wide activation (Multisite)<\/td><\/tr><tr><td><code>Requires at least<\/code><\/td><td>No<\/td><td>Minimum WordPress version<\/td><\/tr><tr><td><code>Requires PHP<\/code><\/td><td>No<\/td><td>Minimum PHP version<\/td><\/tr><tr><td><code>Requires Plugins<\/code><\/td><td>No<\/td><td>Comma-separated plugin slugs (6.5+)<\/td><\/tr><tr><td><code>Update URI<\/code><\/td><td>No<\/td><td>Custom update server URI<\/td><\/tr><\/tbody><\/table><\/figure><h2 class=\"wp-block-heading\">Plugin Activation Lifecycle<\/h2><h3 class=\"wp-block-heading\">Activation Flow<\/h3><ol class=\"wp-block-list\"><li><code>validate_plugin()<\/code> &#8211; Verify plugin file exists and has valid header<\/li><li><code>validate_plugin_requirements()<\/code> &#8211; Check WP\/PHP version compatibility<\/li><li><code>activate_plugin<\/code> action fires<\/li><li><code>activate_{$plugin}<\/code> action fires (used by <code>register_activation_hook()<\/code>)<\/li><li>Plugin added to <code>active_plugins<\/code> option<\/li><li><code>activated_plugin<\/code> action fires<\/li><\/ol><h3 class=\"wp-block-heading\">Deactivation Flow<\/h3><ol class=\"wp-block-list\"><li><code>deactivate_plugin<\/code> action fires<\/li><li><code>deactivate_{$plugin}<\/code> action fires (used by <code>register_deactivation_hook()<\/code>)<\/li><li>Plugin removed from <code>active_plugins<\/code> option<\/li><li><code>deactivated_plugin<\/code> action fires<\/li><\/ol><h3 class=\"wp-block-heading\">Uninstall Methods<\/h3><p>Two options for cleanup when plugin is deleted:<\/p><ol class=\"wp-block-list\"><li><p><strong>Uninstall Hook<\/strong> (via <code>register_uninstall_hook()<\/code>)<\/p><ul class=\"wp-block-list\"><li>Must be a static method or function<\/li><li>Stored in <code>uninstall_plugins<\/code> option<\/li><\/ul><\/li><li><p><strong>uninstall.php File<\/strong><\/p><ul class=\"wp-block-list\"><li>Place <code>uninstall.php<\/code> in plugin root<\/li><li>Check for <code>WP_UNINSTALL_PLUGIN<\/code> constant<\/li><li>Preferred for complex uninstall routines<\/li><\/ul><\/li><\/ol><h2 class=\"wp-block-heading\">Pluggable Functions<\/h2><p><strong>Uninstall Hook<\/strong> (via <code>register_uninstall_hook()<\/code>)<\/p><h3 class=\"wp-block-heading\">How Pluggable Functions Work<\/h3><div class=\"code-block-wrapper\"><div class=\"code-block-header\"><span class=\"code-block-language\">php<\/span><button class=\"code-copy-btn\" aria-label=\"Copy code\"><svg><use href=\"https:\/\/chubes.net\/wp-content\/themes\/chubes\/assets\/icons\/chubes.svg#icon-copy\"><\/use><\/svg><\/button><\/div><pre data-chubes-enhanced class=\"wp-block-code language-php\"><code class=\"language-php\">\/\/ In wp-includes\/pluggable.php\nif ( ! function_exists( &#039;wp_mail&#039; ) ) :\n    function wp_mail( $to, $subject, $message, ... ) {\n        \/\/ Default implementation\n    }\nendif;<\/code><\/pre><\/div><h3 class=\"wp-block-heading\">Overriding Pluggable Functions<\/h3><p><strong>uninstall.php File<\/strong><\/p><div class=\"code-block-wrapper\"><div class=\"code-block-header\"><span class=\"code-block-language\">php<\/span><button class=\"code-copy-btn\" aria-label=\"Copy code\"><svg><use href=\"https:\/\/chubes.net\/wp-content\/themes\/chubes\/assets\/icons\/chubes.svg#icon-copy\"><\/use><\/svg><\/button><\/div><pre data-chubes-enhanced class=\"wp-block-code language-php\"><code class=\"language-php\">\/\/ In mu-plugin or early-loading plugin\nfunction wp_mail( $to, $subject, $message, ... ) {\n    \/\/ Custom implementation\n}<\/code><\/pre><\/div><h3 class=\"wp-block-heading\">Categories of Pluggable Functions<\/h3><p><strong>Uninstall Hook<\/strong> (via <code>register_uninstall_hook()<\/code>)<\/p><ul class=\"wp-block-list\"><li>Must be a static method or function<\/li><li>Stored in <code>uninstall_plugins<\/code> option<\/li><\/ul><p><strong>uninstall.php File<\/strong><\/p><ul class=\"wp-block-list\"><li>Place <code>uninstall.php<\/code> in plugin root<\/li><li>Check for <code>WP_UNINSTALL_PLUGIN<\/code> constant<\/li><li>Preferred for complex uninstall routines<\/li><\/ul><p>WordPress defines certain functions as &quot;pluggable&quot; &#8211; they can be replaced by defining them before WordPress loads <code>pluggable.php<\/code>. This allows complete override of core functionality.<\/p><ul class=\"wp-block-list\"><li>Must be a static method or function<\/li><li>Stored in <code>uninstall_plugins<\/code> option<\/li><\/ul><p>Define the function in a plugin that loads before <code>pluggable.php<\/code>:<\/p><ul class=\"wp-block-list\"><li>Place <code>uninstall.php<\/code> in plugin root<\/li><li>Check for <code>WP_UNINSTALL_PLUGIN<\/code> constant<\/li><li>Preferred for complex uninstall routines<\/li><\/ul><p><strong>Authentication &amp; Users:<\/strong><\/p><ul class=\"wp-block-list\"><li><code>wp_set_current_user()<\/code>, <code>wp_get_current_user()<\/code><\/li><li><code>get_userdata()<\/code>, <code>get_user_by()<\/code>, <code>cache_users()<\/code><\/li><li><code>wp_authenticate()<\/code>, <code>wp_logout()<\/code><\/li><li><code>is_user_logged_in()<\/code>, <code>auth_redirect()<\/code><\/li><\/ul><p><strong>Password &amp; Security:<\/strong><\/p><ul class=\"wp-block-list\"><li><code>wp_hash_password()<\/code>, <code>wp_check_password()<\/code><\/li><li><code>wp_set_password()<\/code>, <code>wp_generate_password()<\/code><\/li><li><code>wp_verify_nonce()<\/code>, <code>wp_create_nonce()<\/code><\/li><li><code>wp_salt()<\/code>, <code>wp_hash()<\/code><\/li><\/ul><p><strong>Cookies &amp; Sessions:<\/strong><\/p><ul class=\"wp-block-list\"><li><code>wp_set_auth_cookie()<\/code>, <code>wp_clear_auth_cookie()<\/code><\/li><li><code>wp_validate_auth_cookie()<\/code>, <code>wp_generate_auth_cookie()<\/code><\/li><li><code>wp_parse_auth_cookie()<\/code><\/li><\/ul><h2 class=\"wp-block-heading\">Best Practices<\/h2><h3 class=\"wp-block-heading\">Plugin Development<\/h3><ol class=\"wp-block-list\"><li>Use namespaces or class prefixes to avoid conflicts<\/li><li>Register hooks at appropriate priority levels<\/li><li>Always sanitize input and escape output<\/li><li>Use nonces for form submissions and AJAX<\/li><li>Check user capabilities before actions<\/li><li>Load scripts\/styles only where needed<\/li><\/ol><h3 class=\"wp-block-heading\">Activation\/Deactivation<\/h3><ol class=\"wp-block-list\"><li>Keep activation hooks lightweight<\/li><li>Use transients for expensive one-time operations<\/li><li>Clean up all options\/data on uninstall<\/li><li>Don&#8217;t run arbitrary code at top level<\/li><\/ol><h3 class=\"wp-block-heading\">Pluggable Function Override<\/h3><ol class=\"wp-block-list\"><li>Only override when absolutely necessary<\/li><li>Consider using filters\/hooks instead<\/li><li>Maintain compatibility with expected behavior<\/li><li>Test thoroughly &#8211; affects entire site<\/li><\/ol><h2 class=\"wp-block-heading\">Related Files<\/h2><ul class=\"wp-block-list\"><li><code>wp_mail()<\/code> &#8211; Primary email sending function<\/li><li><code>wp_notify_postauthor()<\/code>, <code>wp_notify_moderator()<\/code><\/li><li><code>wp_new_user_notification()<\/code>, <code>wp_password_change_notification()<\/code><\/li><\/ul>","protected":false},"excerpt":{"rendered":"<p>The Plugin API is WordPress&#8217;s system for extending core functionality through modular code packages. It encompasses plugin loading, activation lifecycle, pluggable functions, and mu-plugins. Plugin Types Standard Plugins (wp-content\/plugins\/) Installed&#8230;<\/p>\n","protected":false},"featured_media":0,"template":"","meta":{"footnotes":""},"tags":[],"project":[646],"project_type":[749],"class_list":["post-5723","documentation","type-documentation","status-publish","hentry","project-plugins","project_type-wordpress-reference"],"project_info":{"id":589,"name":"WordPress Core","slug":"wordpress-core"},"project_type_info":{"id":749,"name":"WordPress Reference","slug":"wordpress-reference"},"_links":{"self":[{"href":"https:\/\/chubes.net\/wp-json\/wp\/v2\/documentation\/5723","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/chubes.net\/wp-json\/wp\/v2\/documentation"}],"about":[{"href":"https:\/\/chubes.net\/wp-json\/wp\/v2\/types\/documentation"}],"version-history":[{"count":3,"href":"https:\/\/chubes.net\/wp-json\/wp\/v2\/documentation\/5723\/revisions"}],"predecessor-version":[{"id":8820,"href":"https:\/\/chubes.net\/wp-json\/wp\/v2\/documentation\/5723\/revisions\/8820"}],"wp:attachment":[{"href":"https:\/\/chubes.net\/wp-json\/wp\/v2\/media?parent=5723"}],"wp:term":[{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/chubes.net\/wp-json\/wp\/v2\/tags?post=5723"},{"taxonomy":"project","embeddable":true,"href":"https:\/\/chubes.net\/wp-json\/wp\/v2\/project?post=5723"},{"taxonomy":"project_type","embeddable":true,"href":"https:\/\/chubes.net\/wp-json\/wp\/v2\/project_type?post=5723"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}