How to register a basic plugin with header and activation in PHP in WordPress

Contents

Introduction

This article is a complete, detailed tutorial on creating a basic WordPress plugin that includes a proper plugin header and activation logic in PHP. Youll learn the required plugin header format, how to register activation and deactivation callbacks, how to create database tables safely on activation, how to clean up on uninstall, important security and best-practice notes, and practical code examples you can drop into a plugin file.

What a plugin needs at minimum

A WordPress plugin must be a PHP file placed inside wp-content/plugins/ and contain a plugin header comment block at the top. That header lets WordPress identify the plugin and show it in the Plugins screen. To run activation logic you register a callback with register_activation_hook. For deactivation use register_deactivation_hook. For uninstall cleanup use register_uninstall_hook or create an uninstall.php file that WordPress will call.

Minimal plugin header example


Registering an activation hook

Use register_activation_hook( __FILE__, your_activation_function ). The hook triggers when a user activates the plugin via the WordPress admin. The activation callback should be lightweight and must not produce output (no echo/print) because activation runs during HTTP headers processing. If you need to show status or errors to the admin, save a transient or option and render an admin notice on the next admin page load.

Simple activation and deactivation example


Creating database tables on activation (dbDelta)

If your plugin needs its own database tables, use the WordPress function dbDelta which safely creates or updates tables. Important steps:

  • Use wpdb-gtprefix to prefix your table name.
  • Use wpdb-gtget_charset_collate() to set charset/collation correctly.
  • Include require_once( ABSPATH . wp-admin/includes/upgrade.php ) before calling dbDelta.
  • Make sure SQL column definitions are formatted precisely to match dbDelta expectations (e.g., same spacing and use of key names).

Activation example creating a table

prefix . pwtb_items
    charset_collate = wpdb->get_charset_collate()

    // SQL must use the exact format expected by dbDelta.
    sql = CREATE TABLE {table_name} (
        id bigint(20) NOT NULL AUTO_INCREMENT,
        name varchar(191) NOT NULL,
        value text NOT NULL,
        created_at datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
        PRIMARY KEY  (id)
    ) {charset_collate}

    require_once ABSPATH . wp-admin/includes/upgrade.php
    dbDelta( sql )

    // Save plugin version for later upgrades.
    add_option( pwtb_version, PWTB_VERSION )
}

register_activation_hook( PWTB_PLUGIN_FILE, pwtb_activate )

Deactivation and uninstall

Deactivation is for stopping plugin behavior and optionally cleaning up runtime data (transients, scheduled jobs). Uninstall should remove persistent data like options and custom tables if the plugin author chooses to do so. There are two ways to implement uninstall behavior:

  • Create an uninstall.php file at the plugin root. WordPress will load and run it when the plugin is uninstalled from admin. Remember to check for defined(WP_UNINSTALL_PLUGIN) to guard the file.
  • Use register_uninstall_hook( __FILE__, my_uninstall_function ).

uninstall.php example (recommended for most cases)

prefix . pwtb_items
wpdb->query( DROP TABLE IF EXISTS {table_name} )

Using register_uninstall_hook example

prefix . my_plugin_table
    wpdb->query( DROP TABLE IF EXISTS {table} )
}

register_uninstall_hook( __FILE__, my_plugin_uninstall )

Class-based plugin structure (recommended)

Encapsulating functionality in a class avoids polluting the global namespace and makes maintenance easier. Use a bootstrap that instantiates the main class. You can still hook activation to the class static method.

Class-based plugin with activation/deactivation


Common activation pitfalls and how to handle them

  • Do not echo output during activation. Activation runs before the admin page is displayed output can break headers. To inform the user, set an option or transient and display an admin notice on the next admin page load.
  • Multisite (Network) activation: If the plugin is network-activated, WordPress will run the activation hook once for the network. If you require per-site setup, iterate over sites using get_sites() and switch_to_blog() to run per-site installation code.
  • File path for register_activation_hook: Use the main plugin file path (commonly __FILE__). If registering the hook from an included file, ensure the constant points at the main plugin file path you want WordPress to correlate with.
  • Long running operations: Avoid long operations during activation (e.g., processing thousands of items). Instead set a flag and schedule a background job (using Cron or an async approach) to perform heavy migration tasks.

Example: reporting activation errors using admin notice

. esc_html( msg ) .

delete_transient( my_plugin_activation_error ) } } register_activation_hook( __FILE__, my_plugin_activate )

Security and hardening guidelines

Internationalization

Make your plugin translatable by including a Text Domain in the header and using the translation functions __(), _e(), _n(), etc. Load the textdomain on init using load_plugin_textdomain().


Versioning and upgrade routines

Store your plugin version in an option (e.g., my_plugin_version) and on plugin init compare the saved version with the current version. If they differ, run upgrade routines (migrations, schema changes), then update the option. This handles upgrades safely without relying solely on activation.


Testing activation, deactivation and uninstall

  1. Install the plugin zip or copy the plugin folder into wp-content/plugins/.
  2. Activate from the WordPress Admin gt Plugins and verify activation tasks ran (check options, tables, admin notices).
  3. Deactivate and ensure deactivation cleanup (transients, cron) happened.
  4. Uninstall the plugin and confirm persistent data (options, tables) were removed if you chose to delete them.
  5. Test on a Multisite installation if you plan to support Multisite test single-site activation and network activation flows.

Packaging and other best practices

  • Include a readme.txt with plugin description and changelog (format used by WordPress.org if you plan to host there).
  • Keep the main plugin file short: bootstrap and delegate logic to includes or class files.
  • Prefix all functions, classes, options, and database table names to avoid collisions with other plugins.
  • Follow semantic versioning for your plugin version.
  • Document activation side-effects in your readme (e.g., which tables/options are created).

Complete example: a small plugin with header, activation (table creation), deactivation and uninstall

Put the following code into a plugin file such as my-complete-plugin.php. Also add uninstall.php shown earlier if you want full uninstall behavior.

prefix . mcp_items
        charset_collate = wpdb->get_charset_collate()

        sql = CREATE TABLE {table_name} (
            id bigint(20) NOT NULL AUTO_INCREMENT,
            title varchar(191) NOT NULL,
            content longtext NOT NULL,
            created_at datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
            PRIMARY KEY  (id)
        ) {charset_collate}

        require_once ABSPATH . wp-admin/includes/upgrade.php
        dbDelta( sql )

        add_option( mcp_version, self::VERSION )
    }

    public static function deactivate() {
        // Clear transients, unschedule cron jobs, etc.
        delete_transient( mcp_cache )
    }

    // Note: do NOT uninstall persistent data here use uninstall.php or register_uninstall_hook.
}

register_activation_hook( __FILE__, array( My_Complete_Plugin, activate ) )
register_deactivation_hook( __FILE__, array( My_Complete_Plugin, deactivate ) )

// Boot the plugin.
My_Complete_Plugin::instance()

Quick reference of functions and hooks

  • register_activation_hook( file, callback ) — register activation callback.
  • register_deactivation_hook( file, callback ) — register deactivation callback.
  • register_uninstall_hook( file, callback ) — register uninstall callback (or use uninstall.php).
  • dbDelta( sql ) — create/upgrade tables. Include upgrade.php first.
  • wpdb->prefix — use this to name custom tables.
  • get_option / add_option / update_option / delete_option — manage options.

Conclusion

Following the practices above will give you a robust, safe starting point for any WordPress plugin that needs to perform initialization during activation and clean up on uninstall. Use proper headers, protect direct access, follow security and i18n guidelines, avoid long tasks in activation, and consider background jobs for heavy migrations. The included examples provide the most common patterns to register activation/deactivation hooks, create database tables, and remove persistent data on uninstall.



Acepto donaciones de BAT's mediante el navegador Brave 🙂



Leave a Reply

Your email address will not be published. Required fields are marked *