WordPress 插件开发最小可用示例(含后台设置页)
先说结论:一个合格的 WordPress 插件最少需要三样东西——头部声明、一个钩子挂载点、一个可选的设置页。下面从零写一个「文章末尾自动加版权声明」的插件,全部代码不到 100 行,可以直接改成你自己要的功能。 一、目录与文件结构 wp-
先说结论:一个合格的 WordPress 插件最少需要三样东西——头部声明、一个钩子挂载点、一个可选的设置页。下面从零写一个「文章末尾自动加版权声明」的插件,全部代码不到 100 行,可以直接改成你自己要的功能。
一、目录与文件结构
wp-content/plugins/my-copyright/
├── my-copyright.php (主文件,必须)
└── readme.txt (可选,但建议有)
常见错误:文件夹名和主文件名不一致、主文件放在子目录里,都会导致后台看不到插件。
二、主文件头部声明(少了它插件不出现)
<?php
/*
Plugin Name: My Copyright
Description: 在文章末尾追加版权声明。
Version: 1.0.0
Author: Your Name
License: GPL-2.0-or-later
Text Domain: my-copyright
*
if ( ! defined( 'ABSPATH' ) ) {
exit; // 防止直接访问文件
}
Plugin Name 是后台显示的名字,必须有。ABSPATH 判断是安全基线的第一步,所有插件都该有。
三、挂第一个钩子:过滤器 the_content
add_filter( 'the_content', 'myc_append_copyright' );
function myc_append_copyright( $content ) {
// 只在单篇文章页、主循环里生效
if ( ! is_singular( 'post' ) || ! in_the_loop() || ! is_main_query() ) {
return $content;
}
$text = get_option( 'myc_text', '本文为原创内容,转载请注明出处。' );
$html = '<div class="myc-copyright">' . esc_html( $text ) . '</div>';
return $content . $html;
}
三个判断条件缺一不可:
is_singular('post'):避免出现在列表页、页面、归档页。in_the_loop():避免影响侧栏、相关文章等二次循环。is_main_query():避免影响查询结果里的其他内容。
漏了这三个判断,最常见的现象是「版权声明出现在所有地方,包括后台摘要和 RSS」。
四、加一个后台设置页(3 个函数就够)
1. 在后台菜单注册页面
add_action( 'admin_menu', 'myc_add_menu' );
function myc_add_menu() {
add_options_page(
'版权声明设置', // 页面标题
'My Copyright', // 菜单名
'manage_options', // 权限
'my-copyright', // slug
'myc_render_page' // 回调
);
}
manage_options 是关键权限,只有管理员能看。权限写小了普通用户看不见,写大了有安全问题。
2. 渲染表单
function myc_render_page() {
?>
<div class="wrap">
<h1>版权声明设置</h1>
<form method="post" action="options.php">
<?php settings_fields( 'myc_group' ); ?>
<?php do_settings_sections( 'myc_group' ); ?>
<table class="form-table">
<tr>
<th><label for="myc_text">声明文字</label></th>
<td>
<input type="text" id="myc_text" name="myc_text"
value="<?php echo esc_attr( get_option( 'myc_text' ) ); ?>"
class="regular-text">
</td>
</tr>
</table>
<?php submit_button(); ?>
</form>
</div>
<?php
}
注意 action="options.php" 是 WordPress 处理设置保存的入口,不要改成自己的地址。esc_attr() 输出时必须转义。
3. 注册设置项
add_action( 'admin_init', 'myc_register_settings' );
function myc_register_settings() {
register_setting( 'myc_group', 'myc_text', [
'type' => 'string',
'sanitize_callback' => 'sanitize_text_field',
'default' => '本文为原创内容,转载请注明出处。',
] );
}
sanitize_callback 是必填的,不写就可能被写入 HTML 或脚本。这是插件审核被打回最多的原因之一。
五、加上样式(只在本页加载)
add_action( 'wp_enqueue_scripts', 'myc_enqueue' );
function myc_enqueue() {
wp_register_style( 'myc-style', false );
wp_enqueue_style( 'myc-style' );
wp_add_inline_style( 'myc-style', '.myc-copyright{border-top:1px solid #eee;padding-top:12px;margin-top:24px;font-size:14px;color:#666}' );
}
用 wp_add_inline_style 就不需要额外的 css 文件,适合极小的插件。
六、卸载时清理数据
在插件目录建 uninstall.php:
<?php
if ( ! defined( 'WP_UNINSTALL_PLUGIN' ) ) { exit; }
delete_option( 'myc_text' );
不写这个文件,用户删了插件,数据库里还留着 option,属于不干净的做法。
七、命名前缀这件事,别嫌啰嗦
PHP 里函数名是全局的,两个插件用同名函数会直接白屏。规范做法:
- 所有函数加统一前缀(如
myc_)。 - 或者用类包装,把函数收进 class 里。
- option 名、slug、样式句柄也统一前缀。
真实事故:某站装了 A 插件和 B 插件,两者都有 get_meta(),一启用就 Fatal error。改名 5 分钟的事,排查要 2 小时。
八、自测清单
| 检查项 | 状态 |
|---|---|
| 后台能看到插件并启用 | □ |
| 文章页出现声明,列表页没有 | □ |
| 设置页能保存并回显 | □ |
| 普通用户看不到设置页 | □ |
| WP_DEBUG 开启下无 notice | □ |
| 禁用后前台无残留 | □ |
把这个示例跑通,你就已经会了 WordPress 插件开发的核心三件事:钩子、设置、安全转义。剩下都是往这个骨架上加功能。