Mastering WordPress Plugin Development: Building Your First Custom Plugin from Scratch

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

Why choose WordPress plugin development?

As the world's most popular content management system, WordPress owes its strong scalability largely to its plugins. By developing custom plugins, you can add unique features to the core platform to meet specific business needs without having to modify the theme files. This ensures that your custom code will not be lost when the theme is updated, and it also makes the functionality modular, making it easy to reuse across different websites.

Learning plugin development not only allows you to create products that others can use, but also enables you to gain a deeper understanding of the workings of WordPress, including its hook system, database interactions, and best practices for security. This is a crucial step in progressing from being an ordinary user to an advanced developer.

Build your first plugin

Before you start writing code, you need to set up a standard WordPress environment on your local computer or on a test server. This is the foundation for all development work.

Recommended Reading Learn WordPress plugin development from scratch: Build your first custom feature

Create the main file of the plug-in

Every WordPress plugin must have a main file, which is usually named after the plugin itself. We will create a file named…my-first-pluginThe plugin. First of all, in the WordPress installation directory under your…/wp-content/plugins/Inside the folder, create a new folder and name it…my-first-plugin

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%.

Within this folder, create a file namedmy-first-plugin.phpThis is the PHP file for the plugin. This file serves as the entry point for the plugin. Open it and add the following plugin header comments; this information is crucial for WordPress to recognize your plugin.

<?php
/**
 * Plugin Name:       我的第一个插件
 * Plugin URI:        https://yourwebsite.com/my-first-plugin
 * Description:       这是一个学习WordPress插件开发的示例插件,用于在文章底部添加自定义内容。
 * Version:           1.0.0
 * Author:            你的名字
 * Author URI:        https://yourwebsite.com
 * License:           GPL v2 or later
 * Text Domain:       my-first-plugin
 * Domain Path:       /languages
 */

Implementing the first simple function

A classic feature for beginners is the automatic addition of a piece of text at the bottom of all article contents on a website. We will be using this feature with WordPress. the_content This is achieved using filter hooks. Add the following function below the comments at the top of your main file:

// 防止直接访问文件
if ( ! defined( 'ABSPATH' ) ) {
    exit;
}

/**
 * 在文章内容末尾添加自定义文本
 *
 * @param string $content 原始的文章内容。
 * @return string 修改后的文章内容。
 */
function mfp_add_footer_text( $content ) {
    // 判断是否是主循环且在单篇文章页面
    if ( is_single() &amp;&amp; in_the_loop() &amp;&amp; is_main_query() ) {
        $custom_text = '<div class="mfp-footer-note"><p><em>Thank you for reading! This article is brought to you by “My First Plugin”.</em></p></div>';
        return $content . $custom_text;
    }
    return $content;
}
// 将函数挂载到 `the_content` 过滤器上
add_filter( 'the_content', 'mfp_add_footer_text' );

This piece of code defines a function. mfp_add_footer_textIt receives the content of the article. $content As a parameter, the function first checks whether the current environment is on a single article page, within the main loop, or during the main query. This is to prevent the addition of text to the summary, widgets, or other areas of the page. If the conditions are met, the function creates a custom piece of HTML text and appends it to the original content.

Deep Dive into Plugin Architecture and Security

As the number of plugin functions increases, good code organization becomes essential. At the same time, security is the lifeline of all WordPress development efforts.

Recommended Reading Learn WordPress plugin development: Build your first extension module from scratch

Restructure the code using object-oriented programming.

To improve the maintainability and scalability of the code, it is recommended to use an object-oriented (OOP) approach to organize plugins. We will refactor the above functionality into a class.

// 防止直接访问文件
if ( ! defined( 'ABSPATH' ) ) {
    exit;
}

class My_First_Plugin {
    /**
     * 构造函数,初始化插件钩子。
     */
    public function __construct() {
        // 在构造方法中将方法挂载到钩子上
        add_action( 'init', array( $this, 'load_textdomain' ) );
        add_filter( 'the_content', array( $this, 'add_footer_to_content' ) );
        add_action( 'wp_enqueue_scripts', array( $this, 'enqueue_styles' ) );
    }

/**
     * 加载插件的文本翻译域。
     */
    public function load_textdomain() {
        load_plugin_textdomain( 'my-first-plugin', false, dirname( plugin_basename( __FILE__ ) ) . '/languages' );
    }

/**
     * 在文章内容末尾添加自定义文本。
     */
    public function add_footer_to_content( $content ) {
        if ( is_single() &amp;&amp; in_the_loop() &amp;&amp; is_main_query() ) {
            $custom_text = '<div class="mfp-footer-note"><p><em>' . esc_html__( '感谢阅读!本文由“我的第一个插件”为您呈现。', 'my-first-plugin' ) . '</em></p></div>';
            return $content . $custom_text;
        }
        return $content;
    }

/**
     * 为插件添加样式。
     */
    public function enqueue_styles() {
        wp_enqueue_style( 'mfp-style', plugins_url( 'assets/css/style.css', __FILE__ ), array(), '1.0.0' );
    }
}

// 实例化插件类
$my_first_plugin_instance = new My_First_Plugin();

Please note that we are… add_footer_to_content The method uses… esc_html__() The function is used to wrap text. It acts as a translation function and also performs appropriate escaping on the output, which is the best practice for securely displaying text. We have also added a method to load style sheets and introduced support for text fields, preparing the plugin for internationalization (i18n).

Understanding and implementing data validation and escaping

Never trust user input or any external data. Whenever you receive, process, or output data, you must validate, clean it, and escape it accordingly. For example, if you want to create a management page with an input form, be sure to use the functions provided by WordPress that are designed to prevent common security issues (such as cross-site scripting, unauthorized access, etc.). These functions include those related to non-ce (Cross-Site Embedding) protection, permission checks, and data validation.

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%

The functionality of this plugin is relatively simple, but we have already used it when generating the HTML output. esc_html__() Escape the data. If a plugin needs to process data submitted by users, such as through a form, it is essential to use appropriate escape mechanisms to ensure that the data is correctly interpreted and processed. sanitize_text_field(), wp_kses_post() Clean up the functions using the appropriate methods, and then proceed with their use. wp_verify_nonce() This is to verify the legitimacy of the request.

Create a plugin management page

A mature plugin usually requires a backend configuration page. We will learn how to use WordPress’s settings API to create a simple, standard administration page.

Add a plugin settings menu

First of all, we need to add a sub-menu page under the “Settings” menu in the WordPress backend. Add a new method to your class, and call it within the constructor. add_action('admin_menu', ...) The hook calls it.

Recommended Reading WordPress Plugin Development Beginner’s Guide: Building Your First Functional Plugin from Scratch

/**
 * 注册插件管理页面。
 */
public function register_admin_menu() {
    add_options_page(
        __( '我的插件设置', 'my-first-plugin' ), // 页面标题
        __( '我的第一个插件', 'my-first-plugin' ), // 菜单标题
        'manage_options', // 所需权限
        'mfp-settings', // 菜单slug
        array( $this, 'display_settings_page' ) // 显示页面的回调函数
    );
}

Then, add the following in the constructor:add_action( 'admin_menu', array( $this, 'register_admin_menu' ) );

Build a settings page and its fields.

Next, we need to define display_settings_page A method used to render the HTML content of the settings page and to register a settings field using the settings API.

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.
/**
 * 显示插件设置页面。
 */
public function display_settings_page() {
    ?&gt;
    <div class="wrap">
        <h1></h1>
        <form action="/en/options.php/" method="post" data-trp-original-action="options.php">
            <?php
            // 输出设置字段、非ce等安全字段
            settings_fields( 'mfp_settings_group' );
            do_settings_sections( 'mfp-settings' );
            submit_button();
            ?>
        <input type="hidden" name="trp-form-language" value="en"/></form>
    </div>
    <?php
}

/**
 * 初始化插件设置。
 */
public function initialize_settings() {
    // 注册一个设置
    register_setting(
        'mfp_settings_group', // 设置组名
        'mfp_footer_text', // 选项名
        array(
            'type' => 'string',
            'sanitize_callback' =&gt; 'sanitize_text_field', // 清理回调函数
            'default' =&gt; __( '感谢阅读!本文由“我的第一个插件”为您呈现。', 'my-first-plugin' ),
        )
    );

// 添加一个设置区域
    add_settings_section(
        'mfp_main_section',
        __( '主要设置', 'my-first-plugin' ),
        null, // 可选的区域描述回调函数
        'mfp-settings'
    );

// 向区域中添加字段
    add_settings_field(
        'mfp_footer_field',
        __( '页脚文本', 'my-first-plugin' ),
        array( $this, 'render_footer_field' ), // 渲染字段的回调函数
        'mfp-settings',
        'mfp_main_section',
        array( 'label_for' =&gt; 'mfp_footer_text' )
    );
}

You need to define… render_footer_field Methods to render the actual input fields and update the previous state. add_footer_to_content Method to retrieve it from the database options get_option('mfp_footer_text') Read the text from a file instead of using hardcoded strings. Finally, add the following code to the constructor:add_action( 'admin_init', array( $this, 'initialize_settings' ) );

summarize

Throughout this journey, you built a fully functional WordPress plugin from scratch. You learned how to create the basic structure of a plugin, how to use action and filter hooks to extend WordPress’s functionality, how to organize your code in an object-oriented manner to improve its quality, how to follow security best practices for data validation and escaping, and how to utilize the WordPress Settings API to create a professional administrative interface for backend management.

The core of plugin development lies in understanding WordPress’s hook system and data flow. Continuously practice by starting with simple functions, gradually increasing the complexity of your plugins, and always prioritize security, performance, and maintainability. As you gain more experience, you will be able to create powerful, professional, and popular WordPress plugins.

FAQ Frequently Asked Questions

What are the basic knowledge requirements for developing WordPress plugins?

You need to have a solid understanding of PHP programming, as the plugin is primarily written in PHP. It is also necessary to have a basic knowledge of HTML, CSS, and JavaScript, as you will be responsible for handling the front-end display and interactions. Most importantly, you should be familiar with the core concepts of WordPress, such as hooks (actions and filters), loops, template hierarchy, and database operations using classes like WP_Query and WP_User_Query.

How to debug and test my plugin?

First of all, it is highly recommended to develop your code in a local development environment (such as Local by Flywheel or XAMPP) or on a test site online, to avoid impacting the live production website. Enable the debugging mode in WordPress.wp-config.phpSettings are defined in the file.define( 'WP_DEBUG', true );This will display PHP errors and warnings on the screen. Use it.error_log()The function logs custom debugging information to the server’s error log. For more advanced debugging, you may consider using professional debugging tools such as Query Monitor or Debug Bar.

How can my plugin be compatible with different versions of WordPress?

During development, it is important to pay attention to the notifications in the WordPress official documentation regarding deprecated functions. Avoid using functions that have been marked as “deprecated”. In the main file of your plugin, you can…Requires at leastandTested up toUse the header information to specify the compatible version of WordPress. Regularly test your plugin on newer versions of WordPress and keep an eye on the core update logs to make timely adjustments to your code.

How do I publish my plugin to the official WordPress plugin directory?

First of all, you need to make sure that your plugin fully complies with the official plugin development guidelines and submission requirements. This includes aspects such as code quality, security, and the license agreement (it must be GPLv2 or a more recent version). Next, apply for an SVN repository on WordPress.org. Then, submit your plugin code to that SVN repository.trunkIt is included in the directory, and the corresponding files have been created.readme.txtThe file must be in a specific format. Once it has passed the review process, your plugin will be added to the official directory.