WordPress Plugin Basics and Development Environment
Before starting to write code, it is essential to understand the basic concepts of WordPress plugins and set up a suitable development environment. A WordPress plugin is essentially a folder that contains PHP code, which is used to extend the core functionality of WordPress through the rich API provided by the platform. Plugins can range from simple additions that just involve a few lines of code to complex systems that manage entire aspects of a website. The key principle behind plugin development is to “never modify the core code”; this ensures that your custom functionality will not be lost when WordPress is upgraded.
For efficient development, you need a local development environment. You can use tools such as XAMPP, MAMP, Local by Flywheel, or Docker to quickly set up a server with PHP and MySQL. After that, install the latest version of WordPress. During the development process, it is recommended to…wp-config.phpEnable in the file.WP_DEBUGThis is to ensure that errors can be identified and addressed in a timely manner.
The “heart” of a plugin is a main PHP file. The comments at the beginning of this file serve as its identification information; WordPress uses this metadata to recognize and manage the plugin in the background. The standard comments at the beginning of a plugin’s main file are as follows:
Recommended Reading What are WordPress Themes。
<?php
/**
* Plugin Name: 我的第一个自定义插件
* Plugin URI: https://example.com/my-first-plugin
* Description: 这是一个用于学习插件开发的简单插件,它将在文章末尾添加自定义内容。
* Version: 1.0.0
* Author: 开发者名称
* License: GPL v2 or later
* Text Domain: my-first-plugin
*/ Create your first functional plug-in
Let’s start with a practical feature: automatically adding a custom piece of text at the end of each article on the website. This example will illustrate the core process of plugin development.
Plugin main file and initialization
First of all, in WordPress…wp-content/pluginsCreate a new folder under the directory, for examplemy-first-pluginInside this folder, create the main PHP file, which can be named…my-first-plugin.phpCopy the above header comment code into the appropriate place.
Next, we need a secure way to execute the initialization code for the plugin. The best practice is to wrap all the functionality within a class or use namespace functions. Here, we will use a simple class to organize the code. After the header comments in the main file, add the following class definition:
if ( ! defined( 'ABSPATH' ) ) {
exit; // 防止直接访问文件
}
class My_First_Plugin {
public function __construct() {
// 构造函数,在这里挂载钩子
}
}
// 初始化插件
new My_First_Plugin(); if ( ! defined( ‘ABSPATH’ ) )This line of code is part of the security standards for WordPress plugin development, designed to prevent users from directly accessing your plugin files via a URL.
Use hooks to add content to the article footer.
WordPress’s plugin architecture is built on a system of “hooks,” which are divided into two main categories: Actions and Filters. Actions allow you to execute code at specific moments in the plugin’s execution process, while Filters enable you to modify data that is being processed by the plugin.
Recommended Reading The Ultimate Guide to WordPress Website Performance Optimization: From Basic Configuration to a Comprehensive Analysis of Caching Plugins。
Our goal is to add text after the article content; this is a process of “filtering” the content. Therefore, we will use…the_contentModify the constructor and methods in the class as follows:
class My_First_Plugin {
public function __construct() {
// 将自定义方法挂载到‘the_content’过滤器上
add_filter( 'the_content', array( $this, 'add_footer_to_content' ) );
}
/**
* 在文章内容后添加自定义页脚
*
* @param string $content 原始文章内容。
* @return string 修改后的文章内容。
*/
public function add_footer_to_content( $content ) {
// 确保只在主循环的单篇文章页面显示
if ( is_single() && in_the_loop() && is_main_query() ) {
$custom_footer = '<div class="my-plugin-footer"><p>Thank you for reading this article! It was generated by [My First Plugin].</p></div>';
$content .= $custom_footer;
}
return $content;
}
} add_filter()The function will use the class method.add_footer_to_contentRegister tothe_contentFilters: When WordPress is ready to display the content of an article, it calls our method and passes in the original text. We use conditional logic to ensure that the footer is only added to the individual article pages, preventing it from being displayed on the home page or archive pages. Finally, we append the customized HTML code to the content and return the result.
Add management backend options for the plugin.
A mature plugin usually allows users to make configurations in the background. We will add a simple setting option for the footer text just now, so that users can customize the text that is displayed.
Create a settings menu page.
We need to add a sub-page under the “Settings” menu in the WordPress administration panel. This will require the use of…add_options_page()The function is usually mounted (or made available for use) in...admin_menuOn the action hook.
First, add a new method to the plugin class to register menus and pages:
class My_First_Plugin {
// ... 之前的构造函数和方法 ...
public function __construct() {
add_filter( 'the_content', array( $this, 'add_footer_to_content' ) );
// 挂载后台管理菜单
add_action( 'admin_menu', array( $this, 'add_admin_menu' ) );
// 挂载初始化设置选项
add_action( 'admin_init', array( $this, 'settings_init' ) );
}
public function add_admin_menu() {
add_options_page(
'我的第一个插件设置', // 页面标题
'自定义页脚设置', // 菜单标题
'manage_options', // 所需权限
'my-first-plugin', // 菜单slug
array( $this, 'options_page_html' ) // 回调函数,用于输出页面HTML
);
}
} Registration settings fields and the rendered page
Next, we need to use the WordPress Settings API to securely register, save, and validate options. This involves…register_setting(), add_settings_section()andadd_settings_field()Functions such as...
Recommended Reading What is WooCommerce? This article provides a detailed explanation of its core functions and application scenarios.。
public function settings_init() {
// 注册一个设置选项组
register_setting( 'my_first_plugin_settings', 'my_first_plugin_options' );
// 在页面中添加一个设置区域
add_settings_section(
'my_first_plugin_section',
'页脚内容配置',
array( $this, 'section_callback' ),
'my-first-plugin'
);
// 向该区域添加一个字段
add_settings_field(
'footer_text',
'页脚显示文本',
array( $this, 'footer_text_field_render' ),
'my-first-plugin',
'my_first_plugin_section'
);
}
public function section_callback() {
echo '<p>Configure the text content that will be displayed at the end of the article here.</p>';
}
public function footer_text_field_render() {
$options = get_option( 'my_first_plugin_options' );
$value = $options['footer_text'] ?? '感谢阅读本文!由【我的第一个插件】生成。'; // 默认值
?>
<input type='text' name='my_first_plugin_options[footer_text]' value='<?php echo esc_attr( $value ); ?>' style='width: 400px;'>
<p class="description">Supports simple HTML tags, such as <strong>, <em>, <a>。</p>
<?php
}
public function options_page_html() {
// 检查用户权限
if ( ! current_user_can( 'manage_options' ) ) {
return;
}
?>
<div class="wrap">
<h1></h1>
<form action='/en/options.php/' method='post' data-trp-original-action="options.php">
<p><strong>Output:</strong>
</p>
<input type="hidden" name="trp-form-language" value="en"/></form>
</div>
<?php
} Finally, modify the front-end output function.add_footer_to_contentRead the text from the database options.
public function add_footer_to_content( $content ) {
if ( is_single() && in_the_loop() && is_main_query() ) {
$options = get_option( 'my_first_plugin_options' );
$footer_text = $options['footer_text'] ?? '感谢阅读本文!由【我的第一个插件】生成。';
$custom_footer = '<div class="my-plugin-footer"><p>'. wp_kses_post($Footer_text)'. ‘</p></div>';
$content .= $custom_footer;
}
return $content;
} wp_kses_post()The function ensures that only safe HTML tags are allowed in the user input, which is an important security measure.
Plugin Internationalization and Best Practices
In order for plugins to be used by users around the world, internationalization (i18n) is an essential step. WordPress uses the GNU gettext framework to handle translations.
Text fields and translation functions
First of all, make sure that the definitions are included in the comments at the top of your plugin’s header file.Text DomainFor examplemy-first-pluginThen, in the plugin, wrap all the strings that need to be translated using a specific function.
Modify our previous code to add translation support for the output text.
\n// Load the translation file in the constructor
public function __construct() {
// ... other hooks ...
add_action( 'plugins_loaded', array( $this, 'load_textdomain' ) );
}
public function load_textdomain() {
load_plugin_textdomain(
'my-first-plugin',
false,
dirname( plugin_basename( __FILE__ ) ) . '/languages/'
);
}
// Modify the strings on the settings page
public function section_callback() {
echo ' \n// Load the translation file in the constructor
public function __construct() {
// ... other hooks ...
add_action( 'plugins_loaded', array( $this, 'load_textdomain' ) );
}
public function load_textdomain() {
load_plugin_textdomain(
'my-first-plugin',
false,
dirname( plugin_basename( __FILE__ ) ) . '/languages/'
);
}
// Modify the strings on the settings page
public function section_callback() {
echo '<p>'\n' . esc_html__( 'Here, you can configure the text content that will be displayed at the end of the article.', 'my-first-plugin' ) . '</p>';
}
public function footer_text_field_render() {
$options = get_option( 'my_first_plugin_options' );
$value = $options['footer_text'] ?? __( '感谢阅读本文!由【我的第一个插件】生成。', 'my-first-plugin' );
?>
<input type='text' name='my_first_plugin_options[footer_text]' value='<?php echo esc_attr( $value ); ?>' style='width: 400px;'>
<p class="description"><p><strong>Support for simple HTML tags, such as <strong>, <em>, <a>.</strong></p>
<?php esc_html_e( 'Support for simple HTML tags, such as <strong>, <em>, <a>.', 'my-first-plugin' ); ?></p>
<?php
}
// Note: The “footer text” entered by users on the front end usually doesn't need to be translated, as it is specific content set by the administrator. __()Used to translate and return a string.esc_html__()Used for translating and escaping HTML output._e()This function is used to translate and directly display a string. The second parameter of the function is the text field, which must match the one defined by the plugin.
Security, Performance, and Code Organization
In addition to internationalization, the following best practices should also be followed:
1. Security: Validate, clean, and escape all user input. Use…sanitize_text_field(), esc_html(), wp_kses_post()and other functions. Use it to...wp_nonce_field()Prevent CSRF (Cross-Site Request Forgery) attacks.
2. Performance: Use hooks wisely to avoid performing unnecessary database queries with each page load. Consider implementing a transient cache for the output results.
3. Code Organization: For complex plugins, the files should be divided into functional modules. The main file should serve as the entry point, while classes and methods should be placed in separate files accordingly.includes/Table of contents: Front-end assets (CSS, JS) are placed in…assets/Catalog.
4. Uninstallation and cleanup: If your plugin has created database tables or options, it should provide an uninstallation function to remove those data. This can be achieved through a separate...uninstall.phpThis can be achieved by using a file.
summarize
Through this tutorial, we completed the entire development process for a WordPress custom plugin with basic functionality: from setting up the environment, creating the plugin skeleton, adding features using the hook system, to implementing the backend settings page, and finally covering internationalization and security best practices. You have learned how to use these tools and techniques to build custom plugins for WordPress.add_filterandadd_actionInteracting with the WordPress core, how to use the Settings API to create reliable option pages, and how to proceed with that…load_plugin_textdomainMake the plugin support multiple languages. Remember that when developing plugins, security, maintainability, and user experience should be the top priorities. Based on these principles, you can further explore more advanced features such as custom post types, metadata, shortcodes, and REST API endpoints to build even more powerful WordPress extensions.
FAQ Frequently Asked Questions
Why doesn't my plugin show up in the background menu?
This is usually caused by permission issues or code errors. First of all, please make sure that your…add_options_pageOradd_menu_pageThe permission parameters specified within the function (such as…)‘manage_options’It must match the user role with which you are currently logged in. Secondly, please perform a check.admin_menuCheck whether the hook is correctly installed, and ensure that there are no syntax errors in the callback function that could cause PHP execution to be interrupted. The simplest way to do this is to enable the hook from within the WordPress administration panel.WP_DEBUGCheck to see if any relevant error messages are displayed.
How to add custom CSS and JavaScript files for a plugin?
The correct approach is to usewp_enqueue_style()andwp_enqueue_script()For front-end resources, they should be mounted to the appropriate location.wp_enqueue_scriptsOn the action hook; for backend management resources, it is mounted to…admin_enqueue_scriptsOn the hook.
In your plugin class, you can add the following methods:
public function enqueue_frontend_assets() {
wp_enqueue_style( ‘my-plugin-style’, plugin_dir_url( __FILE__ ) . ‘assets/css/style.css’, array(), ‘1.0.0’ );
} Then, in the constructor, use it through…add_action( ‘wp_enqueue_scripts’, array( $this, ‘enqueue_frontend_assets’ ) );Register. This ensures that dependency management is done correctly and that there are no conflicts with other plugins or themes.
How can I clean up the data options I created when users uninstall the plugin?
WordPress provides two main methods. The first is to register a uninstall hook, but this is not commonly used in object-oriented plugins. The more recommended and standard approach is to create…uninstall.phpThe file is in the same directory as your main plugin file.
When a user deletes a plugin through the WordPress administration panel, WordPress automatically checks and executes the code contained in that file.uninstall.phpIn this case, you need to check first.WP_UNINSTALL_PLUGINAre the constants defined first? Then, all options created by the plugin, as well as custom database tables and other data, should be securely deleted. For example:
if ( ! defined( ‘WP_UNINSTALL_PLUGIN’ ) ) {
exit;
}
delete_option( ‘my_first_plugin_options’ );
// 如果有自定义表:$wpdb->query( “DROP TABLE IF EXISTS {$wpdb->prefix}my_table” ); How can my plugin be compatible with more versions of WordPress?
The key to maintaining compatibility lies in using new functions and features with caution, and providing alternatives for older versions. Before calling a function that may only be available in the new version, make sure to…function_exists()For inspection purposes. For example, if you want to use features introduced in version 5.0…wp_dateFunctions can:
if ( function_exists( ‘wp_date’ ) ) {
$date = wp_date( get_option( ‘date_format’ ), $timestamp );
} else {
$date = date_i18n( get_option( ‘date_format’ ), $timestamp );
} Also, clearly state the minimum WordPress version that has been tested in the plugin’s header comments and the readme file. Regularly testing on older versions of WordPress is the best way to ensure compatibility.
What's next, what's next?
Extended reading and practical knowledge
The following are related to the topic of this article and are suitable for further in-depth reading. Prioritize starting with the article that is closest to your current problem, and gradually expanding to surrounding topics usually works better.
- Why Choose WordPress: The Top Ten Core Advantages of an Open-Source CMS
- Master WooCommerce in Ten Minutes: A Guide to Building an E-commerce Website from Scratch to Profit
- WooCommerce Complete Guide: An Advanced E-commerce Configuration Tutorial from Installation to Live Deployment
- What is WordPress? A comprehensive introduction to a content management system
- Preface: Why choose WordPress for development?