博客
WordPress 钩子架构:动作与过滤器详解
每个优秀插件的基础。了解 PAGEnza AI 如何使用钩子和过滤器来创建可维护、可扩展的代码。
每个 WordPress 插件都做两件事之一:它在特定时刻运行代码(动作),或者在值被使用前修改它(过滤器)。就是这样。整个 WordPress 插件生态系统都建立在此区分之上。
理解区别——以及何时使用它们——是区分能正常工作的插件和会引起问题的插件的关键。
动作:在特定时间点执行操作
动作钩子是 WordPress(或其他插件)在特定时刻发出的信号。您将一个函数附加到该信号,当信号触发时,您的函数就会运行。
add_action( 'wp_enqueue_scripts', 'my_plugin_load_assets' );
function my_plugin_load_assets() {
wp_enqueue_style( 'my-plugin', plugin_dir_url( __FILE__ ) . 'style.css' );
wp_enqueue_script( 'my-plugin', plugin_dir_url( __FILE__ ) . 'script.js', ['jquery'], '1.0', true );
}
wp_enqueue_scripts 在 WordPress 准备为前端加载资源时触发。挂钩到它是在加载 CSS 和 JS 的正确方法——而不是直接将 <script> 标签放入模板。
您将经常使用的常见动作钩子:
init— 早期运行,适用于注册文章类型和分类法wp_enqueue_scripts— 加载前端资源admin_enqueue_scripts— 加载后台资源save_post— 在文章保存时运行,适用于处理自定义字段wp_ajax_{action}— 处理已认证用户的 AJAX 请求wp_ajax_nopriv_{action}— 处理未登录用户的 AJAX 请求
过滤器:在值被使用前修改它
过滤器钩子会给您一个值,让您修改它,并期望您返回修改后的版本。然后 WordPress 使用您修改后的值而不是原始值。
add_filter( 'the_content', 'my_plugin_append_cta' );
function my_plugin_append_cta( $content ) {
if ( ! is_single() ) {
return $content;
}
$cta = '<div class="post-cta">准备尝试 PAGEnza? <a href="#">免费开始 →</a></div>';
return $content . $cta;
}
关键规则:始终从过滤器返回某些内容。如果您忘记了 return,该值将变为 null,您将破坏任何使用它的东西。
常见的过滤器钩子:
the_content— 显示前的文章内容the_title— 文章标题wp_nav_menu_items— 导航菜单 HTMLupload_mimes— 允许的文件上传类型plugin_action_links_{plugin-file}— 在插件列表页面显示的链接
PAGEnza AI 如何使用钩子
当插件生成器生成插件时,它会在构造函数中围绕一个类及其附加到钩子的方法来构建代码。这种模式可以避免全局函数名冲突并保持代码的组织性。
class My_Plugin {
public function __construct() {
add_action( 'init', [ $this, 'register_post_type' ] );
add_action( 'wp_enqueue_scripts', [ $this, 'load_assets' ] );
add_filter( 'the_content', [ $this, 'append_content' ] );
}
public function register_post_type() { /* ... */ }
public function load_assets() { /* ... */ }
public function append_content( $content ) {
// always return
return $content;
}
}
new My_Plugin();
安全扫描特别检查 AJAX 处理程序是否在执行任何操作之前包含 nonce 检查和权限检查:
add_action( 'wp_ajax_my_action', [ $this, 'handle_ajax' ] );
public function handle_ajax() {
// Security: verify nonce
check_ajax_referer( 'my_nonce_action', 'nonce' );
// Security: verify permissions
if ( ! current_user_can( 'manage_options' ) ) {
wp_send_json_error( 'Insufficient permissions', 403 );
}
// Now safe to process
$data = sanitize_text_field( $_POST['data'] ?? '' );
wp_send_json_success( [ 'result' => $data ] );
}
缺少其中任何一个都会被标记为安全问题,并阻止插件发布。
优先级和钩子队列
当多个函数附加到同一个钩子时,它们会按照优先级(数字越小,运行越早)的顺序运行。默认优先级为 10。
add_action( 'init', 'runs_first', 5 );
add_action( 'init', 'runs_second', 10 ); // default
add_action( 'init', 'runs_last', 20 );
当您的插件需要在另一个插件的代码之前或之后运行时,这一点很重要。如果您正在修改另一个插件也修改的内容,优先级将决定谁获胜。
常见模式:如果您要覆盖主题的过滤器,请使用优先级 20 或更高,以确保在主题代码之后运行。
删除钩子
您可以删除别人添加的钩子——包括主题和插件钩子:
remove_action( 'wp_head', 'wp_generator' ); // 从 <head> 中移除 WP 版本
remove_filter( 'the_content', 'wpautop' ); // 移除自动段落包装
诀窍是:您只能在原始 add_action/add_filter 运行后调用 remove_action/remove_filter 来删除钩子。这通常意味着将您的删除操作挂钩到一个更晚的动作。