名称: wordpress-plugin-core 描述: WordPress插件开发,包含钩子、安全、REST API、自定义文章类型。适用于插件创建、$wpdb查询、Settings API,或遇到SQL注入、XSS、CSRF、nonce错误。
关键词: wordpress插件开发, wordpress安全, wordpress钩子, wordpress过滤器, wordpress数据库, wpdb准备, sanitize_text_field, esc_html, wp_nonce, 自定义文章类型, register_post_type, settings api, rest api, admin-ajax, wordpress sql注入, wordpress xss, wordpress csrf, 插件头, 激活钩子, 停用钩子, wordpress编码标准, wordpress插件架构 许可证: MIT
WordPress插件开发(核心)
状态: 生产就绪 最后更新: 2025-11-27 依赖项: 无(WordPress 5.9+, PHP 7.4+) 最新版本: WordPress 6.7+, PHP 8.0+ 推荐
快速开始(10分钟)
1. 选择插件结构
提供三种架构模式(详见 references/plugin-architectures.md 获取详细示例):
- 简单(仅函数) - 小型插件,函数少于5个
- OOP - 中型插件,功能相关
- PSR-4(命名空间 + Composer) - 现代标准(2025年),最易维护
2. 创建插件头
每个插件必须在主文件中有一个头注释:
<?php
/**
* 插件名称: 我的超赞插件
* 描述: 简短描述。
* 版本: 1.0.0
* 最低要求: 5.9
* 要求PHP: 7.4
* 文本域: my-plugin
*/
if ( ! defined( 'ABSPATH' ) ) exit;
关键: 插件名称必需,文本域必须与插件slug完全匹配。
3. 安全基础(5个要点)
// 1. 唯一前缀(4-5字符)
function mypl_init() { /* 代码 */ }
add_action( 'init', 'mypl_init' );
// 2. ABSPATH检查(每个文件)
if ( ! defined( 'ABSPATH' ) ) exit;
// 3. Nonces用于表单
wp_nonce_field( 'mypl_action', 'mypl_nonce' );
// 4. 清理输入,转义输出
$clean = sanitize_text_field( $_POST['input'] );
echo esc_html( $output );
// 5. 预处理语句
$wpdb->get_results( $wpdb->prepare( "SELECT * FROM {$wpdb->prefix}table WHERE id = %d", $id ) );
五步安全基础
步骤1: 所有内容使用唯一前缀
规则: 最少4-5字符,应用于函数、类、常量、选项、瞬态、元键。避免 wp_、__、_。
// 良好
function mypl_init() {}
class MyPL_Settings {}
add_option( 'mypl_option', 'value' );
// 错误 - 会冲突
function init() {}
class Settings {}
步骤2: 检查权限,而非仅管理员状态
// 错误
if ( is_admin() ) { /* 安全漏洞 */ }
// 正确
if ( current_user_can( 'manage_options' ) ) { /* 安全 */ }
常用权限: manage_options(管理员)、edit_posts(编辑)、publish_posts(作者)
步骤3: 安全三要素
输入 → 处理 → 输出(清理 → 验证 → 转义):
// 清理(输入)
$name = sanitize_text_field( $_POST['name'] );
$email = sanitize_email( $_POST['email'] );
$url = esc_url_raw( $_POST['url'] );
$html = wp_kses_post( $_POST['content'] );
// 验证(逻辑)
if ( ! is_email( $email ) ) wp_die( '无效邮箱' );
// 转义(输出)
echo esc_html( $name );
echo '<a href="' . esc_url( $url ) . '">' . esc_html( $text ) . '</a>';
规则: 清理输入,转义输出。永远不要信任用户数据。
步骤4: Nonces(CSRF防护)
一次性令牌,证明请求来自您的网站。
// 表单
<form method="post">
<?php wp_nonce_field( 'mypl_action', 'mypl_nonce' ); ?>
<input type="text" name="data" />
</form>
// 验证
if ( ! wp_verify_nonce( $_POST['mypl_nonce'], 'mypl_action' ) ) wp_die( '安全检查失败' );
// AJAX
check_ajax_referer( 'mypl-ajax-nonce', 'nonce' );
步骤5: 数据库的预处理语句
关键: 对于用户输入,始终使用 $wpdb->prepare()。
// 错误 - SQL注入
$wpdb->get_results( "SELECT * FROM {$wpdb->prefix}table WHERE id = {$_GET['id']}" );
// 正确
$wpdb->get_results( $wpdb->prepare( "SELECT * FROM {$wpdb->prefix}table WHERE id = %d", $_GET['id'] ) );
占位符: %s(字符串)、%d(整数)、%f(浮点数)
LIKE查询: 在添加通配符前使用 $wpdb->esc_like():
$search = '%' . $wpdb->esc_like( $term ) . '%';
$wpdb->get_results( $wpdb->prepare( "... WHERE title LIKE %s", $search ) );
关键规则
必须做
✅ 使用唯一前缀(4-5字符)用于所有全局代码(函数、类、选项、瞬态)
✅ 添加ABSPATH检查到每个PHP文件:if ( ! defined( 'ABSPATH' ) ) exit;
✅ 检查权限(current_user_can()),而不仅仅是 is_admin()
✅ 验证nonces用于所有表单和AJAX请求
✅ 使用 $wpdb->prepare() 用于所有带用户输入的数据库查询
✅ 清理输入,使用 sanitize_*() 函数在保存前
✅ 转义输出,使用 esc_*() 函数在显示前
✅ 刷新重写规则在激活时当注册自定义文章类型
✅ 使用uninstall.php用于永久清理(而非停用钩子)
✅ 遵循WordPress编码标准(缩进用制表符,Yoda条件)
禁止做
❌ 永不使用 extract() - 创建安全漏洞
❌ 永不信任 $_POST/$_GET 而不清理
❌ 永不相接用户输入到SQL - 始终使用 prepare()
❌ 永不单独使用 is_admin() 用于权限检查
❌ 永不输出未清理数据 - 始终转义
❌ 永不使用通用函数/类名 - 始终加前缀
❌ 永不使用短PHP标签 <? 或 <?= - 只使用 <?php
❌ 永不在停用时删除用户数据 - 仅在卸载时
❌ 永不多次注册卸载钩子 - 仅在激活时一次
❌ 永不在主流程中使用 register_uninstall_hook() - 改用 uninstall.php
已知问题预防
此技能预防 20 个记录的问题:
问题 #1: SQL注入
错误: 通过未转义的用户输入损害数据库
来源: https://patchstack.com/articles/sql-injection/(15% 的漏洞)
原因: 直接相接到SQL查询中
预防: 始终使用 $wpdb->prepare() 带占位符
// 易受攻击
$wpdb->query( "DELETE FROM {$wpdb->prefix}table WHERE id = {$_GET['id']}" );
// 安全
$wpdb->query( $wpdb->prepare( "DELETE FROM {$wpdb->prefix}table WHERE id = %d", $_GET['id'] ) );
问题 #2: XSS(跨站脚本)
错误: 在用户浏览器中执行恶意JavaScript 来源: https://patchstack.com(35% 的漏洞) 原因: 输出未清理的用户数据到HTML 预防: 始终使用上下文适当的函数转义输出
// 易受攻击
echo $_POST['name'];
echo '<div class="' . $_POST['class'] . '">';
// 安全
echo esc_html( $_POST['name'] );
echo '<div class="' . esc_attr( $_POST['class'] ) . '">';
问题 #3: CSRF(跨站请求伪造)
错误: 未经授权操作以用户名义执行
来源: https://blog.nintechnet.com/25-wordpress-plugins-vulnerable-to-csrf-attacks/
原因: 无验证请求来自您的网站
预防: 使用nonces配合 wp_nonce_field() 和 wp_verify_nonce()
// 易受攻击
if ( $_POST['action'] == 'delete' ) {
delete_user( $_POST['user_id'] );
}
// 安全
if ( ! wp_verify_nonce( $_POST['nonce'], 'mypl_delete_user' ) ) {
wp_die( '安全检查失败' );
}
delete_user( absint( $_POST['user_id'] ) );
问题 #4: 缺少权限检查
错误: 普通用户可以访问管理功能
来源: WordPress安全审查指南
原因: 使用 is_admin() 而非 current_user_can()
预防: 始终检查权限,而非仅管理员上下文
// 易受攻击
if ( is_admin() ) {
// 任何登录用户都能触发
}
// 安全
if ( current_user_can( 'manage_options' ) ) {
// 仅管理员能触发
}
问题 #5: 直接文件访问
错误: PHP文件在WordPress上下文外执行 来源: WordPress插件手册 原因: 文件顶部无ABSPATH检查 预防: 添加ABSPATH检查到每个PHP文件
// 添加到每个PHP文件顶部
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
附加问题 (#6-20)
对于超出前5个安全漏洞的全面错误覆盖,加载 references/error-catalog.md,其中包括:
- 功能性: 前缀冲突、重写规则未刷新、已弃用函数、文本域不匹配、插件依赖、自动保存触发
- 性能: 脚本到处加载、瞬态未清理、admin-ajax.php性能
- 安全: 保存时缺少清理、不正确的LIKE查询、使用extract()、缺少REST API权限回调、卸载钩子问题
- 数据完整性: 停用时删除数据
每个问题包括:错误描述、来源、原因、预防代码、影响严重性、频率。
插件架构模式
为您的插件大小和复杂性选择正确的架构:
决策指南
简单(仅函数)
- 何时: 小型插件(<5函数)、单一功能
- 优点: 易于开始、最小样板
- 缺点: 不扩展、组织超过~5函数困难
- 示例: 简单短代码插件、基本小工具
OOP(单例模式)
- 何时: 中型插件(5-20函数)、相关功能
- 优点: 更好组织、封装、可测试
- 缺点: 比简单多样板、不使用现代PHP特性
- 示例: 自定义文章类型插件、管理设置页面
PSR-4(命名空间 + Composer)
- 何时: 大型/现代插件、团队开发、2025+ 标准
- 优点: 现代PHP、命名空间、自动加载、最佳实践
- 缺点: 需要Composer、更多初始设置
- 示例: 电子商务扩展、多功能插件
完整示例
对于完整的实现示例、目录结构、激活钩子和代码模式,加载 references/plugin-architectures.md。
常见实现模式
此技能提供8个常见WordPress插件功能的生产就绪模式:
- 自定义文章类型 - 注册带Gutenberg支持的CPT、刷新重写规则
- 自定义分类法 - 分层(分类)或平面(标签)分类法
- 元框 - 保存自定义字段带适当安全(nonces、权限、自动保存检查)
- Settings API - WordPress原生设置页面带清理
- REST API端点 - 现代API端点带权限回调和验证
- AJAX处理器 - 传统admin-ajax.php模式(新项目使用REST API)
- 自定义数据库表 - 创建表带dbDelta、版本控制
- 瞬态用于缓存 - 缓存昂贵操作、更新时清理
对于完整实现代码,在实现任何这些功能时加载 references/common-patterns.md。每个模式包括:
- 完整工作代码示例
- 安全要求清单
- 常见错误避免
- 最佳实践和性能提示
分发和自动更新
托管在WordPress.org外的插件可以使用 Plugin Update Checker 由 YahnisElsts(推荐)提供自动更新。
快速解决方案:
- 公开仓库: Plugin Update Checker(GitHub/GitLab/BitBucket)
- 私有插件: Plugin Update Checker + 认证令牌
- 商业插件: Freemius 或 自定义更新服务器
- 无需编码: Git Updater插件
对于完整实现,加载 references/github-auto-updates.md,其中包括:
- Plugin Update Checker设置(5分钟)
- GitHub发布工作流
- 私有仓库认证
- 安全最佳实践(校验和、令牌、速率限制)
- 替代方案比较
- ZIP结构要求
依赖项
必需:
- WordPress 5.9+(推荐6.7+)
- PHP 7.4+(推荐8.0+)
可选:
- Composer 2.0+ - 用于PSR-4自动加载
- WP-CLI 2.0+ - 用于命令行插件管理
- Query Monitor - 用于调试和性能分析
官方文档
- WordPress插件手册: https://developer.wordpress.org/plugins/
- WordPress编码标准: https://developer.wordpress.org/coding-standards/
- WordPress REST API: https://developer.wordpress.org/rest-api/
- WordPress数据库类 ($wpdb): https://developer.wordpress.org/reference/classes/wpdb/
- WordPress安全: https://developer.wordpress.org/apis/security/
- Settings API: https://developer.wordpress.org/plugins/settings/settings-api/
- 自定义文章类型: https://developer.wordpress.org/plugins/post-types/
- 瞬态API: https://developer.wordpress.org/apis/transients/
- Context7库ID: /websites/developer_wordpress
故障排除
致命错误: 启用 WP_DEBUG,检查 wp-content/debug.log,验证带前缀的名称
CPT上404: 刷新重写规则(临时在wp-admin中添加 flush_rewrite_rules();)
Nonce失败: 检查匹配名称、正确操作、24小时过期
AJAX返回0/-1: 验证操作名称匹配 wp_ajax_{action}、nonce发送/验证、处理器钩住
HTML被剥离: 使用 wp_kses_post() 而非 sanitize_text_field()
数据库查询失败: 始终使用 $wpdb->prepare(),包括 $wpdb->prefix,验证语法
何时加载参考文件
此技能使用 渐进式披露 - 主文件包含要点,参考文件有详细实现。根据您当前任务加载参考:
references/common-patterns.md(465行)
何时加载: 实现特定WordPress功能时 包含:
- 自定义文章类型(注册、Gutenberg支持、重写规则)
- 自定义分类法(分层 vs 平面、REST API)
- 元框(安全要求、保存钩子、自动保存检查)
- Settings API(register_setting、部分、字段层次)
- REST API端点(权限回调、验证、响应)
- AJAX处理器(nonce验证、wp_ajax钩子、JavaScript集成)
- 自定义数据库表(dbDelta、字符编码、版本控制)
- 瞬态用于缓存(缓存模式、失效、过期)
references/plugin-architectures.md(220行)
何时加载: 选择插件结构或模式间迁移时 包含:
- 简单模式(仅函数,<5函数)
- OOP模式(单例、封装、中型插件)
- PSR-4模式(命名空间、Composer自动加载、现代标准)
- 模式选择决策树
- 完整目录结构带所有文件
- 激活/停用钩子示例
- 模式间迁移路径
references/error-catalog.md(问题 #6-20,573行)
何时加载: 调试超出前5个安全漏洞的问题时 包含:
- 功能性问题(前缀冲突、重写规则、已弃用函数、文本域、依赖项、自动保存)
- 性能问题(脚本到处、瞬态清理、admin-ajax.php替代方案)
- 安全问题(清理、extract()、REST权限、卸载钩子)
- 数据完整性问题(停用 vs 卸载) 每个问题包括: 错误描述、来源/参考、原因、预防代码、影响严重性、频率
references/advanced-topics.md(150行)
何时加载: 实现i18n、WP-CLI、定时任务或依赖检查时 包含:
- 国际化(i18n)- load_plugin_textdomain()、翻译工作流、.pot/.po/.mo文件
- WP-CLI命令 - 自定义命令创建、进度条、输出函数
- 定时事件(定时)- wp_schedule_event()、自定义计划、激活钩子
- 插件依赖检查 - 版本要求、软依赖、用户友好错误消息
references/security-checklist.md(527行)
何时加载: 执行安全审计或代码审查漏洞时 包含:
- 完整安全审计清单
- OWASP Top 10 for WordPress
- 每种漏洞类型代码示例
- 测试过程和工具
- 安全插件推荐
references/github-auto-updates.md(1,224行)
何时加载: 为托管在WordPress.org外的插件设置自动更新时 包含:
- Plugin Update Checker(推荐)- 5分钟设置
- GitHub发布工作流和自动化
- 私有仓库认证(令牌、wp-config.php)
- 替代方案(Git Updater、自定义服务器、Freemius)
- 安全最佳实践(校验和、签名、速率限制)
- ZIP结构要求和常见错误
- 部署自动化示例
references/common-hooks.md(234行)
何时加载: 使用WordPress钩子时需要参考时 包含:
- 动作钩子参考(init、admin_menu、save_post等)
- 过滤器钩子参考(the_content、post_type_args等)
- 钩子优先级和执行顺序
- 常见钩子组合和模式
完整设置清单
使用此清单验证您的插件:
- [ ] 插件头完整带所有字段
- [ ] ABSPATH检查在每个PHP文件顶部
- [ ] 所有函数/类使用唯一前缀
- [ ] 所有表单有nonce验证
- [ ] 所有用户输入被清理
- [ ] 所有输出被转义
- [ ] 所有数据库查询使用 $wpdb->prepare()
- [ ] 权限检查(而不仅仅是 is_admin())
- [ ] 自定义文章类型在激活时刷新重写规则
- [ ] 停用钩子仅清除临时数据
- [ ] uninstall.php处理永久清理
- [ ] 文本域匹配插件slug
- [ ] 脚本/样式仅在需要时加载
- [ ] 开发期间启用 WP_DEBUG
- [ ] 使用 Query Monitor 插件测试性能
- [ ] 无已弃用函数警告
- [ ] 与最新WordPress版本兼容
问题?疑问?
- 检查
references/error-catalog.md获取附加问题 #6-20 - 验证安全基础所有步骤
- 检查官方文档: https://developer.wordpress.org/plugins/
- 启用 WP_DEBUG 并检查 debug.log
- 使用 Query Monitor 插件调试钩子和查询