CodeRoadMap
首页路线题库资源库文章社区
CodeRoadMap

程序员的学习成长路线图。内容免费开放,登录后可同步路线图与课时进度。

由 程序员柏风 独立维护 · 关于作者

学习

  • 路线图
  • 课程
  • 面试题
  • 文章
  • 我

更多

  • 资源
  • 社区
  • 关于作者
  • 内容说明

© 2026 CodeRoadMap

津ICP备2026012044号-1·津公网安备12011002026155号·coderoadmap@126.com
WordPress 开发入门/课时/插件生态
RawBlame
课时目录12 节

WordPress 开发入门

  1. 01WordPress 概览
  2. 02环境搭建
  3. 03主题开发
  4. 04区块编辑器
  5. 05插件生态
  6. 06Hooks 与 CPT
  7. 07PHP 架构
  8. 08数据库
  9. 09AJAX 与 Headless
  10. 10安全加固
  11. 11性能与运维
  12. 12综合练习

插件生态

插件基础与 Page builders。

30 分钟

插件开发与 Hook 体系

这一课你将能做到

  1. 从零写出规范插件骨架:主文件头注释、激活/停用/卸载钩子一个不缺
  2. 区分 action 与 filter,用优先级和参数个数精准控制回调的执行顺序
  3. 在文章保存、请求初始化等真实时机挂载自己的逻辑(如保存时自动打标签)

为什么要学

WordPress 的 80% 二次开发是通过 Hook(钩子)完成的:WP 在执行流程的关键节点「喊一声」,你的插件、主题响应它。不改核心、不碰模板,就能改变全站行为——这是 WP 生态繁荣的技术根基,也是面试必考题。

人话:把 WP 想象成流水线,Hook 是流水线上预留的插口。action 插口是「到这一步了,你去干件事」(发邮件、写日志);filter 插口是「这个数据交给你加工,加工完必须还回来」(改标题、追加正文)。分不清这两点,插件开发寸步难行。

先建立图像

一次请求的执行顺序与主要插口:

请求进入
 → 加载 mu-plugins(必用插件,最先)
 → 按字母序加载 plugins            ← 你插件的 add_action 在这里注册
 → 加载主题 functions.php
 → plugins_loaded
 → init                           ← 常用:注册 CPT、_taxonomy
 → wp_loaded → 解析主查询
 → template_redirect / the_content(filter) / wp_enqueue_scripts
 → 渲染模板 → wp_footer → 输出

注册发生在「加载期」,执行发生在「运行期」——所以你可以在 init 之前安全地 add_action,但很多 WP 函数要等 init 之后才能用。

跟着做

步骤 1:插件骨架

wp-content/plugins/qrocmq-toolkit/ 下新建主文件 qrocmq-toolkit.php:

<?php
/**
 * Plugin Name:       QROCMQ Toolkit
 * Description:       课程站工具:保存文章自动追加来源说明。
 * Version:           1.0.0
 * Requires at least: 6.5
 * Requires PHP:      8.2
 * Author:            qrocmq
 * Text Domain:       qrocmq-toolkit
 */

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

保存后后台「插件」页应出现它——头注释就是插件的身份证明。ABSPATH 检查是安全底线。

步骤 2:第一个 action

在骨架下方追加:

add_action( 'admin_notices', function () {
    echo '<div class="notice notice-info"><p>QROCMQ Toolkit 已启用</p></div>';
} );

add_action( 'wp_enqueue_scripts', function () {
    wp_enqueue_style(
        'qrocmq-toolkit',
        plugin_dir_url( __FILE__ ) . 'assets/main.css',
        array(),
        '1.0.0'
    );
} );

激活插件,后台顶部出现提示条——你的第一段代码已进入 WP 执行流程。

步骤 3:filter 实战:改内容必须还数据

add_filter( 'the_content', function ( string $content ): string {
    if ( is_singular( 'post' ) ) {
        $content .= '<p class="source-note">本文首发于 QROCMQ 课程站</p>';
    }
    return $content;   // filter 的铁律:必须 return
}, 20 );               // 优先级 20:晚于默认的 10 执行

add_filter( 'the_title', function ( string $title, int $post_id ): string {
    return is_admin() ? $title : $title . '|课程笔记';
}, 10, 2 );            // 第三个参数:接收 2 个参数

注意 add_filter 第 4 参:默认 1,钩子传几个参数就声明几个,少声明会导致回调收不到数据。

步骤 4:生命周期钩子:激活建数据,卸载要清理

register_activation_hook( __FILE__, function () {
    add_option( 'qrocmq_toolkit_version', '1.0.0' );
    update_option( 'qrocmq_toolkit_activated_at', time() );
} );

register_deactivation_hook( __FILE__, function () {
    wp_cache_flush();   // 停用时收尾
} );

卸载清理单独放 uninstall.php(删除插件时自动执行):

<?php
if ( ! defined( 'WP_UNINSTALL_PLUGIN' ) ) {
    exit;
}
delete_option( 'qrocmq_toolkit_version' );
delete_option( 'qrocmq_toolkit_activated_at' );

步骤 5:在文章保存时做事

add_action( 'save_post', function ( int $post_id, WP_Post $post, bool $update ): void {
    if ( wp_is_post_revision( $post_id ) || wp_is_post_autosave( $post_id ) ) {
        return;                     // 跳过修订与自动保存
    }
    if ( 'post' !== $post->post_type ) {
        return;
    }
    if ( ! current_user_can( 'edit_post', $post_id ) ) {
        return;                     // 能力检查,防越权
    }
    // 示例:给新文章自动加默认标签
    wp_set_post_tags( $post_id, '课程', true );
}, 10, 3 );

步骤 6:自定义钩子,让别人扩展你

// 你的插件里:发布数据前给外部一个修改机会
$data = apply_filters( 'qrocmq_course_payload', $data, $course_id );
do_action( 'qrocmq_after_course_saved', $course_id, $data );

成熟插件(WooCommerce 为代表)整个就是「自定义钩子的集合」。

讲清楚要点

  1. action 与 filter 的唯一本质区别:filter 必须返回值(数据进出),action 只执行(有去无回)。do_action 触发,apply_filters 触发并传递。
  2. 优先级决定顺序,参数个数决定传参:同为 10 按注册先后执行;回调收不到参数,99% 是第 4 参没写。
  3. 加载顺序是纪律:muplugins → plugins → theme functions.php → init。写代码前先问「我现在这个时机,哪些函数可用」。
  4. 防冲突三板斧:函数与常量加前缀(qrocmq_)、用命名空间、类的静态属性存状态。
  5. 数据落地用 Options/Settings API:配置项 add_option/update_option/get_option,不要自己发明存储。

你可能会懵的地方

  • 同一钩子挂了多个回调,顺序是什么? 优先级数字小者先执行,数字相同按注册顺序。用 Query Monitor 的 Hooks 面板能直接看到全部注册。

  • 为什么我的 filter 把页面改空了? 回调漏了 return。filter 链上你的返回值是下一个环节的输入,返回 null 内容就没了。

  • 插件和 functions.php 谁先加载? 插件全部先于主题。所以主题里可以依赖插件提供的函数吗?不行——插件之间也一样,除非挂在 plugins_loaded 之后再判断。

  • 改了插件代码不生效? 依次排查:对象缓存/页面缓存、OPcache、看的是不是生产目录。本地先关缓存再改。

  • 删除插件时 uninstall 钩子没执行? 必须先「停用」再「删除」才会走卸载流程;且逻辑要写进 uninstall.php 而不是 register_uninstall_hook(后者只支持静态回调,官方推荐文件方式)。

错法对照

错法问题正解
filter 回调不 return数据链断裂,内容变空每条分支都 return
add_action( 'init' ) 里 echo输出时机过早,进缓冲区前用 admin_notices / wp_footer 等展示钩子
函数名 add_meta_box() 裸命名与核心或其他插件致命冲突前缀 qrocmq_ 或命名空间
save_post 不排除 revision每次自动保存都触发一遍wp_is_post_revision / autosave 判断
在文件顶层调用 get_option()加载期可能不可用包在 init/plugins_loaded 回调里

卡点急救

  1. 激活即白屏:主文件语法错或致命错误,wp-content/debug.log 看堆栈;可先把插件目录改名使其不加载再修。
  2. 钩子像没执行:拼写核对(save_post 不是 save_post_)、时机核对(早于注册)、参数个数核对;用 Query Monitor → Hooks 确认注册是否在列。
  3. 卸载后数据残留:把清理逻辑迁移到 uninstall.php,并停用→删除走完整流程验证一次。

面试常问

  • action 和 filter 的区别? action 在特定时机执行动作,无返回值要求;filter 接收数据加工后必须返回,可链式串联。API 上对应 do_action/apply_filters 与 add_action/add_filter。

  • 一次页面请求中,插件与主题的加载顺序? mu-plugins → 插件(按文件名字母序)→ 主题 functions.php → init。因此主题可以安全覆盖插件的样式输出,但函数依赖要晚于 plugins_loaded 检查。

  • 需求:文章发布时推送一条消息,怎么实现? 挂 transition_post_status(比 save_post 更精准:能判断从旧状态到 publish),排除修订与自动保存、做能力检查后调用推送;推送失败要容错,不阻塞保存。

自测三问

  1. add_filter( 'the_title', $cb, 10, 2 ) 的 10 和 2 分别控制什么?
  2. 插件激活、停用、卸载三个阶段分别用什么 API 处理?
  3. save_post 钩子里必须排除哪两种情况?为什么?

小结一句话

插件 = 头注释 + 钩子注册 + 生命周期管理;action 管做事、filter 管加工,优先级与参数个数是你控制 WP 执行流程的两只手。

延伸

  • 插件开发官方手册
  • Hook 参考
  • 下一课:开发工作流——wp-env、调试开关与 Query Monitor 的正确组合。
加载本节练习…
← 上一课区块编辑器下一课 →Hooks 与 CPT