WordPress 插件开发完整流程指南
开发环境搭建
本地开发环境
# 推荐使用本地环境 - Local by Flywheel (新手友好) - Laravel Valet + WordPress - Docker + WordPress - XAMPP/WAMP/MAMP
开发工具配置
# 必备工具 1. IDE: PhpStorm / VS Code 2. 调试工具: Query Monitor 插件 3. 版本控制: Git 4. WP CLI (可选但推荐)
项目初始化
创建基础文件结构
your-plugin/ ├── your-plugin.php # 主文件 ├── readme.txt # 插件说明 ├── includes/ # 核心功能目录 │ ├── class-main.php # 主类 │ ├── class-admin.php # 管理后台 │ ├── class-public.php # 前端功能 │ └── class-db.php # 数据库操作 ├── admin/ # 后台资源 │ ├── css/ │ ├── js/ │ └── views/ ├── public/ # 前端资源 │ ├── css/ │ ├── js/ │ └── templates/ ├── languages/ # 多语言 ├── assets/ # 共用静态资源 └── vendor/ # Composer依赖(可选)
主文件头部注释
<?php
/**
* Plugin Name: 你的插件名称
* Plugin URI: https://your-plugin.com
* Description: 插件描述
* Version: 1.0.0
* Author: 你的名字
* Author URI: https://your-website.com
* License: GPL v2 or later
* Text Domain: your-plugin-textdomain
* Domain Path: /languages
*/
// 防止直接访问
if (!defined('ABSPATH')) {
exit;
}
// 定义常量
define('YP_VERSION', '1.0.0');
define('YP_PLUGIN_DIR', plugin_dir_path(__FILE__));
define('YP_PLUGIN_URL', plugin_dir_url(__FILE__));
define('YP_PLUGIN_BASENAME', plugin_basename(__FILE__));
核心开发流程
插件主类设计
class YourPlugin {
private static $instance = null;
public static function get_instance() {
if (null === self::$instance) {
self::$instance = new self();
}
return self::$instance;
}
private function __construct() {
$this->init_hooks();
}
private function init_hooks() {
// 插件激活/停用钩子
register_activation_hook(__FILE__, array($this, 'activate'));
register_deactivation_hook(__FILE__, array($this, 'deactivate'));
// 初始化
add_action('init', array($this, 'init'));
// 后台初始化
if (is_admin()) {
add_action('admin_menu', array($this, 'add_admin_menu'));
add_action('admin_enqueue_scripts', array($this, 'enqueue_admin_assets'));
} else {
// 前端初始化
add_action('wp_enqueue_scripts', array($this, 'enqueue_public_assets'));
}
}
}
数据库操作(可选)
// 创建自定义表
function create_custom_table() {
global $wpdb;
$table_name = $wpdb->prefix . 'your_data';
$charset_collate = $wpdb->get_charset_collate();
$sql = "CREATE TABLE IF NOT EXISTS $table_name (
id mediumint(9) NOT NULL AUTO_INCREMENT,
name varchar(255) NOT NULL,
value text NOT NULL,
created_at datetime DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (id)
) $charset_collate;";
require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
dbDelta($sql);
}
管理后台开发
// 添加管理菜单
public function add_admin_menu() {
add_menu_page(
'插件设置', // 页面标题
'我的插件', // 菜单标题
'manage_options', // 权限
'your-plugin', // 菜单slug
array($this, 'admin_page'), // 回调函数
'dashicons-admin-generic', // 图标
30 // 位置
);
// 子菜单
add_submenu_page(
'your-plugin',
'设置',
'设置',
'manage_options',
'your-plugin-settings',
array($this, 'settings_page')
);
}
// 后台页面渲染
public function admin_page() {
?>
<div class="wrap">
<h1><?php echo esc_html(get_admin_page_title()); ?></h1>
<form method="post" action="options.php">
<?php
settings_fields('your_plugin_settings');
do_settings_sections('your_plugin');
submit_button();
?>
</form>
</div>
<?php
}
前端功能集成
// 前端短代码
public function register_shortcodes() {
add_shortcode('your_plugin_display', array($this, 'display_shortcode'));
}
public function display_shortcode($atts) {
$atts = shortcode_atts(array(
'id' => 0,
'template' => 'default'
), $atts);
ob_start();
// 加载模板
include YP_PLUGIN_DIR . 'public/templates/display.php';
return ob_get_clean();
}
常见的WordPress钩子使用
Action Hooks
// 保存文章时处理
add_action('save_post', 'your_plugin_save_post', 10, 3);
// 用户注册
add_action('user_register', 'your_plugin_user_registered');
// 评论发布
add_action('wp_insert_comment', 'your_plugin_comment_added', 10, 2);
Filter Hooks
// 修改文章内容
add_filter('the_content', 'your_plugin_modify_content');
add_filter('the_title', 'your_plugin_modify_title', 10, 2);
// 自定义重写规则
add_filter('rewrite_rules_array', 'your_plugin_add_rewrite_rules');
安全最佳实践
数据验证和消毒
// 输入验证 $input = sanitize_text_field($_POST['field']); $email = sanitize_email($_POST['email']); $url = esc_url_raw($_POST['url']); $number = intval($_POST['number']); // 输出转义 echo esc_html($title); echo esc_url($url); echo esc_attr($attribute);
权限检查
// 检查用户权限
if (!current_user_can('manage_options')) {
wp_die('权限不足');
}
// 检查nonce
if (!wp_verify_nonce($_POST['_wpnonce'], 'your_action')) {
wp_die('安全验证失败');
}
// 检查AJAX请求来源
check_ajax_referer('your_nonce', 'security');
性能优化
资源加载优化
// 只在需要时加载资源
public function enqueue_admin_assets($hook) {
if ('toplevel_page_your-plugin' !== $hook) {
return;
}
wp_enqueue_style('your-plugin-admin',
YP_PLUGIN_URL . 'admin/css/admin.css',
array(),
YP_VERSION
);
}
// 条件加载JS
public function enqueue_public_assets() {
if (is_page('contact')) {
wp_enqueue_script('your-plugin-public',
YP_PLUGIN_URL . 'public/js/public.js',
array('jquery'),
YP_VERSION,
true
);
}
}
数据库查询优化
// 使用缓存
$cache_key = 'your_plugin_data';
$data = wp_cache_get($cache_key);
if (false === $data) {
global $wpdb;
$data = $wpdb->get_results(
$wpdb->prepare(
"SELECT * FROM {$wpdb->prefix}posts
WHERE post_type = %s
AND post_status = 'publish'
LIMIT %d",
'your_post_type',
10
)
);
wp_cache_set($cache_key, $data, '', 3600);
}
// 使用Transients
$data = get_transient('your_plugin_data');
if (false === $data) {
$data = expensive_query();
set_transient('your_plugin_data', $data, DAY_IN_SECONDS);
}
国际化与本地化
// 加载语言文件
public function load_textdomain() {
load_plugin_textdomain(
'your-plugin-textdomain',
false,
dirname(YP_PLUGIN_BASENAME) . '/languages/'
);
}
// 在代码中使用
echo __('Hello World', 'your-plugin-textdomain');
printf(__('Welcome %s', 'your-plugin-textdomain'), $username);
_e('Save Settings', 'your-plugin-textdomain');
测试与调试
单元测试
// tests/TestYourPlugin.php
class TestYourPlugin extends WP_UnitTestCase {
public function test_plugin_activated() {
$this->assertTrue(
in_array('your-plugin/your-plugin.php',
apply_filters('active_plugins', get_option('active_plugins')))
);
}
public function test_shortcode_output() {
$output = do_shortcode('[your_plugin_display id="1"]');
$this->assertStringContainsString('expected output', $output);
}
}
调试技巧
// 开发环境错误显示
if (defined('WP_DEBUG') && WP_DEBUG) {
add_action('wp_footer', function() {
if (current_user_can('administrator')) {
echo '<!-- Plugin Debug Info -->';
}
});
}
// 日志记录
function your_plugin_log($message) {
if (WP_DEBUG_LOG) {
error_log('[Your Plugin] ' . print_r($message, true));
}
}
部署与发布
WordPress.org 发布要求
- readme.txt 文件必须包含标准格式
- 所有代码必须符合WordPress编码规范
- 没有病毒或恶意代码
- 遵循GPL许可
readme.txt 模板
=== Your Plugin Name ===
Contributors: yourusername
Tags: tag1, tag2, tag3
Requires at least: 5.0
Tested up to: 6.4
Stable tag: 1.0.0
License: GPLv2 or later
License URI: https://www.gnu.org/licenses/gpl-2.0.html
== Description ==
A brief description of what your plugin does.
== Installation ==
1. Upload the plugin files to the `/wp-content/plugins/` directory
2. Activate the plugin through the 'Plugins' screen in WordPress
3. Use the Settings->Plugin Name screen to configure the plugin
== Frequently Asked Questions ==
= Question 1 =
Answer to question 1.
== Changelog ==
= 1.0.0 =
* Initial release
完整开发示例
简单计数器插件
<?php
/**
* Plugin Name: Simple Counter
* Description: A simple visit counter
* Version: 1.0.0
*/
class SimpleCounter {
private static $instance = null;
public static function init() {
if (null === self::$instance) {
self::$instance = new self();
}
return self::$instance;
}
private function __construct() {
add_action('wp_head', array($this, 'count_visit'));
add_shortcode('counter', array($this, 'display_counter'));
register_activation_hook(__FILE__, array($this, 'activate'));
}
public function activate() {
add_option('simple_counter', 0);
}
public function count_visit() {
if (!is_admin()) {
$count = get_option('simple_counter', 0);
update_option('simple_counter', $count + 1);
}
}
public function display_counter() {
$count = get_option('simple_counter', 0);
return '<p>Total visits: ' . esc_html($count) . '</p>';
}
}
SimpleCounter::init();
开发工具推荐
- WP CLI - 命令行管理工具
- Query Monitor - 调试插件
- Loco Translate - 翻译管理
- Advanced Custom Fields - 自定义字段开发
- Git + GitHub - 版本控制
这个流程覆盖了从开发环境搭建到最终部署的完整周期,建议根据实际需求选择合适的部分来实现。
