Complete Guide to WordPress Plugin Development: Building Your First Functional Plugin from Scratch

3-minute read
2026-03-18
2026-06-03
2,513
I earn commissions when you shop through the links below, at no additional cost to you.

Preparation Work and Environment Configuration

Before you start writing code, you need a suitable development environment. This includes a local installation of WordPress, a code editor, and a basic understanding of the relevant concepts and techniques.

First of all, make sure you have a local server environment. You can use tools such as XAMPP, MAMP, Local by Flywheel, or Docker to set it up quickly. After installing and configuring WordPress, you’ll have a secure sandbox environment where you can conduct tests without worrying about affecting your live website.

Secondly, you need a code editor that is easy to use and efficient. Visual Studio Code, PhpStorm, or Sublime Text are all excellent choices. They offer excellent support for PHP, HTML, JavaScript, and CSS, and include features such as code highlighting, auto-completion, and debugging tools.

Recommended Reading From Zero to One: A Guide to WordPress Plugin Development – Getting Started and Best Practices

Finally, it is crucial to understand the basic structure of WordPress plugins. A plugin is essentially one or more PHP files that are stored in the WordPress installation directory. /wp-content/plugins/ Inside the folder, each plugin must have a main file that contains specific plugin header information, which is used to declare the plugin to the WordPress system.

UltaHost WordPress Hosting
30-day refund guarantee, unlimited bandwidth and database usage, free DDoS protection; purchase for 3 years and get a discount of 50%.

Creating and Declaring the Main Plugin File

The first step in creating a plugin is to create the main file and add the correct header comments. This file is usually named after the functionality of the plugin. For example: my-first-plugin.phpPlease do this in your local environment. /wp-content/plugins/ Create a new folder under the directory and name it my-first-pluginThen create the main file inside that folder.

The plugin header is a collection of plugin metadata that tells WordPress the name, description, version, author, and other information about the plugin. Here is a basic example of a plugin header:

<?php
/**
 * Plugin Name:       我的第一个功能插件
 * Plugin URI:        https://example.com/my-first-plugin
 * Description:       这是一个学习 WordPress 插件开发的示例插件,用于展示基础功能。
 * Version:           1.0.0
 * Author:            你的名字
 * License:           GPL v2 or later
 * Text Domain:       my-first-plugin
 * Domain Path:       /languages
 */

After saving this file, log in to your WordPress administration panel and go to the “Plugins” page. You should see a new plugin named “My First Feature Plugin” in the list of plugins. You can activate it at this point, although it doesn’t have any actual functionality yet.

Core Architecture: Action and Filter Hooks

The core of WordPress’s powerful extensibility lies in its Hook system, which allows developers to insert their own code at specific points in the process, or before/after certain data is used. There are two types of hooks: Actions and Filters.

Recommended Reading WordPress Theme Development Beginner's Guide: Building Your Own Website Template from Scratch

Action hooks allow you to execute custom functions when specific WordPress events occur. For example, when an article is published…publish_postWhen loading the menu in the administration backend…admin_menu) or when loading scripts in the header of the web pagewp_enqueue_scriptsUse it. add_action() A function is used to mount your function onto the action hook.

Use action hooks to add a background menu.

Suppose we want to add a settings page for the plugin to the WordPress administration panel. We will use… admin_menu This action hook. Add the code to your main file, after the plugin header information:

// 在管理后台添加菜单
function mfp_add_admin_menu() {
    add_menu_page(
        '我的插件设置',          // 页面标题
        '我的插件',             // 菜单标题
        'manage_options',       // 所需权限
        'my-first-plugin',      // 菜单 slug
        'mfp_settings_page',    // 用于显示页面内容的回调函数
        'dashicons-admin-generic', // 图标(可选)
        80                     // 菜单位置(可选)
    );
}
add_action( 'admin_menu', 'mfp_add_admin_menu' );

// 设置页面的回调函数
function mfp_settings_page() {
    ?&gt;
    <div class="wrap">
        <h1></h1>
        <p>Welcome to the settings page for my first plugin!</p>
    </div>
    &lt;?php
}

Filter hooks allow you to modify data. They receive a value, which, after being processed by your function, must be returned as a modified value. For example, this could be used to modify the title of an article.the_title), and modifying the content of the article.the_content) or modify the length of the excerpt.excerpt_lengthUse it. add_filter() A function is used to mount your function onto the filter hook.

hosting.com Shared Hosting
High performance with AMD EPYC CPUs, NVMe SSD storage and LiteSpeed, 24/7, 24x7 expert in-house support, advanced security measures including SSL, brute force, malware and DDoS protection, savings of up to 73%

Modify the content of the article using a filter

Let’s create a simple feature: automatically add a copyright statement at the end of each article’s content.

// 在文章内容后添加自定义文本
function mfp_add_copyright_to_content( $content ) {
    // 仅对网站前端的主循环中的文章生效
    if ( is_single() &amp;&amp; in_the_loop() &amp;&amp; is_main_query() ) {
        $custom_text = '<p><em>Copyright Statement: The content of this article is owned by this website. Please indicate the source when reproducing it.</em></p>';
        $content .= $custom_text;
    }
    return $content;
}
add_filter( 'the_content', 'mfp_add_copyright_to_content' );

Implement specific functionality: shorthand codes and abbreviations

Shortcodes are a powerful feature provided by WordPress that allow users to insert a simple tag into an article or page in order to... [my_shortcode]This allows for the generation of complex dynamic content or the execution of specific functions. It provides content creators with a great deal of flexibility.

Create and register a simple shortcut code.

Creating a shortcut code requires two steps: first, you need to define the function that will handle the shortcut code, and then… add_shortcode() The function registers it with WordPress. Let’s create a short code that displays the current date and a greeting.

Recommended Reading From Getting Started to Mastering: A Comprehensive Guide and Practical Tutorial for WordPress Plugin Development

// 定义简码的处理函数
function mfp_show_greeting_shortcode( $atts ) {
    // 使用 shortcode_atts 定义默认参数,并合并用户传入的参数
    $atts = shortcode_atts(
        array(
            'name' =&gt; '访客',
        ),
        $atts,
        'greeting'
    );

// 获取当前时间
    $current_time = current_time( 'mysql' );
    $hour = date( 'H', strtotime( $current_time ) );

// 根据时间生成问候语
    if ( $hour &lt; 12 ) {
        $greeting = &#039;上午好&#039;;
    } elseif ( $hour &lt; 18 ) {
        $greeting = &#039;下午好&#039;;
    } else {
        $greeting = &#039;晚上好&#039;;
    }

// 构建输出
    $output = &#039;<div class="mfp-greeting">'$output .= sprintf( '<p>%s, %s!</p>'输出内容:
%s
', esc_html( $atts['name'] ), esc_html( $greeting ) );'<p>The current time is: %s</p>'输出:<p>当前时间:'. esc_html( $current_time ) . '</p>';'</div>';

return $output;
}
// 注册简码,第一个参数是用户使用的标签名
add_shortcode( 'greeting', 'mfp_show_greeting_shortcode' );

Now, users can use it in the article editor. [greeting name="张三"]On the page, the following message will be displayed: “Hello, Zhang San! The current time is: 2026-...”. If no parameters are provided, the default value “Visitor” will be used.

Advanced Practice: Creating Database Tables and Option Pages

More complex plugins may require the ability to store their own data. WordPress offers two main methods for this: using the WordPress Options API to store simple key-value pairs, or creating custom database tables to store structured data.

InterServer Shared Hosting
Shared hosting $2.50 USD per month , first month $0.1 USD promo code tryinterserver, 461 cloud apps scripts, one click install.

Use the Options API to store settings.

The Option API is very suitable for storing plugin configuration information. We will improve the background settings page we created earlier to enable it to save and retrieve simple settings.

First of all, we need to create a form. mfp_settings_page() In the function, add a simple form to handle the settings:

function mfp_settings_page() {
    // 检查用户是否提交了表单
    if ( isset( $_POST['mfp_submit_settings'] ) ) {
        // 安全检查:验证 nonce
        if ( ! isset( $_POST['mfp_settings_nonce'] ) || ! wp_verify_nonce( $_POST['mfp_settings_nonce'], 'mfp_save_settings' ) ) {
            wp_die( '安全验证失败!' );
        }
        // 权限检查
        if ( ! current_user_can( 'manage_options' ) ) {
            wp_die( '权限不足!' );
        }
        // 清理并保存选项
        $custom_message = sanitize_textarea_field( $_POST['custom_message'] );
        update_option( 'mfp_custom_message', $custom_message );
        echo '<div class="notice notice-success is-dismissible"><p>Settings have been saved!</p></div>';
    }

// 从数据库读取现有值
    $saved_message = get_option( 'mfp_custom_message', '这是默认的欢迎信息。' );
    ?&gt;
    <div class="wrap">
        <h1></h1>
        <form method="post" action="" data-trp-original-action="">
            <?php wp_nonce_field( 'mfp_save_settings', 'mfp_settings_nonce' ); ?>
            <table class="form-table">
                <tr>
                    <th scope="row"><label for="custom_message">Custom Message:</label></th>
                    <td>
                        <textarea name="custom_message" id="custom_message" rows="5" cols="50" class="large-text"><?php echo esc_textarea( $saved_message ); ?></textarea>
                        <p class="description">This text will be displayed when the [show_message] shortcut is used.</p>
                    </td>
                </tr>
            </table>
            <?php submit_button( '保存更改', 'primary', 'mfp_submit_settings' ); ?>
        <input type="hidden" name="trp-form-language" value="en"/></form>
    </div>
    &lt;?php
}

Then, we create a new shortcut code to display the saved message:

function mfp_show_message_shortcode() {
    $message = get_option( 'mfp_custom_message', '这是默认的欢迎信息。' );
    return '<div class="mfp-custom-message">'. wp_kses_post( wpautop( $message ) ) . '</div>'add_shortcode( 'show_message', 'mfp_show_message_shortcode' );

Now, administrators can customize the messages on the plugin settings page, while authors only need to use these customized messages in their articles. [show_message] The message can be displayed using a shorthand code.

A custom table is created when the plugin is activated.

For plugins that need to store complex relational data such as orders and logs, it may be necessary to create their own database tables. This is usually done when the plugin is activated. WordPress provides the necessary functionality to accomplish this. register_activation_hook This is used to define the function that runs when activation occurs.

Note: The following code is just an example. In actual development, you need more rigorous error handling and a database abstraction layer (such as ORM). $wpdbThe use of ( ).

// 插件激活时运行的函数
function mfp_create_custom_table() {
    global $wpdb;
    $table_name = $wpdb->prefix . 'mfp_plugin_logs'; // 确保表名唯一
    $charset_collate = $wpdb->get_charset_collate();

$sql = "CREATE TABLE IF NOT EXISTS $table_name (
        id mediumint(9) NOT NULL AUTO_INCREMENT,
        log_time datetime DEFAULT CURRENT_TIMESTAMP NOT NULL,
        user_id bigint(20) DEFAULT 0,
        action varchar(255) NOT NULL,
        details text,
        PRIMARY KEY  (id)
    ) $charset_collate;";

// 引入 WordPress 升级 API,用于执行 dbDelta 函数
    require_once( ABSPATH . 'wp-admin/includes/upgrade.php' );
    dbDelta( $sql );
}
// 注册激活钩子
register_activation_hook( __FILE__, 'mfp_create_custom_table' );

summarize

By following this guide, you have gone through the core processes of WordPress plugin development. Starting from setting up the environment and writing the plugin’s header file, you learned how to use action and filter hooks to extend WordPress’s functionality, provide users with flexible ways to embed content using shortcodes, and understood the basic methods for storing settings using the Options API as well as creating custom database tables. These are the fundamental building blocks for creating a functional plugin. Remember that a well-structured codebase, security measures such as nonce validation and permission checks, and preparation for internationalization are essential components of professional plugin development. Next, you can explore the WordPress REST API, custom post types, metadata (Meta Boxes), as well as the proper integration of front-end scripts and styles, in order to build more complex and powerful plugins.

FAQ Frequently Asked Questions

Can a plugin have only one main file?

That’s not the case. A plugin can contain multiple PHP files, but there must be a main file that contains the plugin’s header information; this file serves as the entry point for WordPress to recognize the plugin. Complex plugins often organize the code for different functions across multiple files and import them through the main file, which facilitates better code management and modularity.

How to securely handle data submitted by users through front-end forms?

When processing data submitted by users, it is essential to perform strict validation, cleaning, and encoding/decoding operations. For user input, use… sanitize_text_field()sanitize_email()sanitize_textarea_field() Use functions such as cleaning to process the data. For the data that is output to the HTML page, apply appropriate processing techniques. esc_html()esc_attr() Or wp_kses_post() Perform escaping. At the same time, be sure to use WordPress’s nonce mechanism to prevent cross-site request forgery (CSRF). current_user_can() Check the user's permissions.

How can my plugin avoid function name conflicts with other plugins?

The best practice is to use namespaces (PHP 5.3+) or to place all functions, classes, and constants under a unique prefix. For example, all functions in this guide start with “mfp_” (an abbreviation for “My First Plugin”). If you use object-oriented programming, encapsulating the code within classes is also an effective way to avoid naming conflicts.

After the development is complete, how can the plugin be distributed or uploaded to the official directory?

To submit a plugin to the official WordPress.org plugin directory, you need to create a plugin package that complies with the directory’s specifications. This typically involves a standardized file structure, which includes… README.txtYou need to provide a detailed translation, compatibility statements, and ensure that the code follows the WordPress coding standards. You must apply for a developer account on WordPress.org and then use the SVN tool to submit the code to the designated repository.