W
WordPress SOPKnowledge Base
Search
← All topics

WordPress Plugin Development

runnable

Plugin file header, activation/deactivation hooks, custom database table creation, and admin settings page pattern for WordPress plugin development.

developmentpluginactivation-hookdatabase
Agent trigger phrases: wordpress plugin development · create wordpress plugin · plugin activation hook · wordpress plugin boilerplate · wp plugin from scratch

Structure WordPress plugins for maintainability. Use activation hooks for setup, always prevent direct access, and store plugin-specific data in custom tables or options.

Plugin Header

<?php
/**
 * Plugin Name: My Custom Plugin
 * Plugin URI: https://example.com/plugin
 * Description: What this plugin does in one sentence.
 * Version: 1.0.0
 * Author: Your Name
 * Author URI: https://example.com
 * License: GPL v2 or later
 * Text Domain: my-plugin
 * Domain Path: /languages
 */

// Prevent direct access
if (!defined('ABSPATH')) {
    exit;
}

// Plugin constants
define('MYPLUGIN_VERSION', '1.0.0');
define('MYPLUGIN_PATH', plugin_dir_path(__FILE__));
define('MYPLUGIN_URL', plugin_dir_url(__FILE__));
define('MYPLUGIN_BASENAME', plugin_basename(__FILE__));

Activation and Deactivation Hooks

register_activation_hook(__FILE__, 'myplugin_activate');
function myplugin_activate() {
    myplugin_create_tables();
    flush_rewrite_rules();
    // Set default options
    add_option('myplugin_settings', [
        'enabled' => true,
        'version' => MYPLUGIN_VERSION,
    ]);
}

register_deactivation_hook(__FILE__, 'myplugin_deactivate');
function myplugin_deactivate() {
    flush_rewrite_rules();
}

Create Custom Database Table

function myplugin_create_tables() {
    global $wpdb;
    $table_name      = $wpdb->prefix . 'myplugin_leads';
    $charset_collate = $wpdb->get_charset_collate();

    $sql = "CREATE TABLE {$table_name} (
        id mediumint(9) NOT NULL AUTO_INCREMENT,
        created_at datetime DEFAULT CURRENT_TIMESTAMP NOT NULL,
        name varchar(100) NOT NULL,
        email varchar(100) NOT NULL,
        message text,
        status varchar(20) DEFAULT 'new',
        PRIMARY KEY (id)
    ) {$charset_collate};";

    require_once ABSPATH . 'wp-admin/includes/upgrade.php';
    dbDelta($sql);
}

Admin Settings Page

function myplugin_admin_menu() {
    add_options_page(
        __('My Plugin Settings', 'my-plugin'),
        __('My Plugin', 'my-plugin'),
        'manage_options',
        'myplugin-settings',
        'myplugin_settings_page'
    );
}
add_action('admin_menu', 'myplugin_admin_menu');

function myplugin_settings_page() {
    if (!current_user_can('manage_options')) {
        return;
    }
    // Render settings form
    echo '<div class="wrap"><h1>' . esc_html(get_admin_page_title()) . '</h1></div>';
}

File Structure

my-plugin/
├── my-plugin.php          # Main plugin file (header here)
├── includes/
│   ├── class-admin.php    # Admin functionality
│   ├── class-frontend.php # Frontend functionality
│   └── class-database.php # DB operations
├── assets/
│   ├── css/
│   └── js/
└── languages/             # Translations (.pot file)