挂钩
挂钩
挂钩是一段代码在特定的预定义位置交互/修改另一段代码的方式。它们构成了插件和主题如何与 WordPress Core 交互的基础,但 Core 本身也广泛使用它们。
有两种类型的钩子:Actions和Filters。要使用其中任何一个,您需要编写一个名为 a 的自定义函数Callback
,然后将其注册到 WordPress 挂钩以执行特定操作或过滤器。
操作允许您添加数据或更改 WordPress 的运行方式。操作将在 WordPress 核心、插件和主题执行的特定点运行。操作的回调函数可以执行某种任务,例如向用户回显输出或将某些内容插入数据库。Action 的回调函数不会将任何内容返回到调用 Action 挂钩。
过滤器使您能够在 WordPress 核心、插件和主题执行期间更改数据。过滤器的回调函数将接受一个变量,修改它,然后返回它。它们旨在以隔离的方式工作,并且永远不应该产生副作用,例如影响全局变量和输出。过滤器期望有一些东西返回给他们。
WordPress 提供了许多可供您使用的挂钩,但您也可以创建自己的挂钩,以便其他开发人员可以扩展和修改您的插件或主题。
操作与过滤器
动作和过滤器之间的主要区别可以总结如下:
- 动作获取它收到的信息,用它做一些事情,并且不返回任何内容。换句话说:它作用于某些东西,然后退出,不向调用钩子返回任何内容。
- 过滤器获取它接收到的信息,以某种方式修改它,然后返回它。换句话说:它过滤一些东西并将其传回钩子以供进一步使用。
另一种说法是:
- 动作会中断代码流以执行某些操作,然后返回到正常流程而不修改任何内容;
- 过滤器用于以特定方式修改某些内容,以便稍后的代码使用该修改。
所指的是通过钩子定义发送的参数列表。稍后部分将详细介绍这一点。
行动Actions
操作是两种类型的Hook之一。它们提供了一种在 WordPress 核心、插件和主题执行的特定点运行函数的方法。Action 的回调函数不会将任何内容返回到调用 Action 挂钩。它们与Filter相对应。这里回顾一下操作和过滤器之间的区别。
添加动作
添加动作的过程包括两个步骤:
创建回调函数
首先,创建一个回调函数。当它所挂接的操作运行时,该函数将运行。
回调函数就像普通函数一样:它应该有前缀,并且应该位于functions.php
可调用的位置。它应该接受的参数将由您挂钩的操作定义;大多数钩子都有明确的定义,因此请查看钩子文档以了解您选择的操作将传递给函数的参数。
分配(钩子)你的回调函数
其次,将回调函数添加到操作中。这称为挂钩,并告诉操作在运行时运行回调函数。
当您的回调函数准备就绪时,使用add_action() 将其挂钩到您选择的操作。至少add_action()
需要两个参数:
string $hook_name
这是您要挂钩的操作的名称,并且callable $callback
您的回调函数的名称。
下面的示例将在执行钩子wporg_callback()
时运行:init
function wporg_callback() {
// do something
}
add_action( 'init', 'wporg_callback' );
您可以参考Hooks章节来获取可用钩子的列表。
随着您获得更多经验,查看 WordPress 核心源代码将使您找到最合适的挂钩。
附加参数
add_action()
可以接受两个附加参数,int $priority
用于指定回调函数的优先级,以及int $accepted_args
将传递给回调函数的参数数量。
优先事项
许多回调函数可以与单个操作挂钩。例如,钩子init
就有很多用途。在某些情况下,您可能需要确保您的回调函数在其他回调函数之前或之后运行,即使这些其他函数可能尚未被挂钩。
WordPress 根据两件事确定回调函数的运行顺序:第一种方法是手动设置优先级。这是使用 的第三个参数完成的add_action()
。
以下是有关优先级的一些重要事实:
- 优先级是正整数,通常在 1 到 20 之间
priority
默认优先级(即未手动提供值时分配的优先级)为 10- 优先级值理论上没有上限,但现实上限为100
优先级为11的函数将在优先级为10的函数之后运行;优先级为 9 的函数将在优先级为 10 的函数之前运行。
确定回调函数顺序的第二种方法是简单地根据它在同一优先级值中注册的顺序。因此,如果两个回调函数以相同的优先级为同一个钩子注册,它们将按照它们注册到该钩子的顺序运行。
例如,以下回调函数都注册到init
钩子中,但具有不同的优先级:
add_action('init', 'wporg_callback_run_me_late', 11);
add_action('init', 'wporg_callback_run_me_normal');
add_action('init', 'wporg_callback_run_me_early', 9);
add_action('init', 'wporg_callback_run_me_later', 11);
在上面的例子中:
- 第一个运行的函数将是
wporg_callback_run_me_early()
,因为它的手动优先级为 9 - 接下来,
wporg_callback_run_me_normal(),
因为它没有设置优先级,所以它的优先级是10 - 接下来,
wporg_callback_run_me_late()
运行,因为它的手动优先级为 11 - 最后
wporg_callback_run_me_later()
是 run:它的优先级也为 11,但它是在wporg_callback_run_me_late()
.
参数数量
有时,回调函数需要接收一些与所挂接的操作相关的额外数据。
例如,当 WordPress 保存帖子并运行钩子时save_post
,它会向回调函数传递两个参数:正在保存的帖子的 ID 和帖子对象本身:
do_action( 'save_post', $post->ID, $post );
当为钩子注册回调函数时save_post
,它可以指定它想要接收这两个参数。它通过add_action
(在本例中)2
作为第四个参数来告诉我们期望它们:
add_action('save_post', 'wporg_custom', 10, 2);
为了在回调函数中实际接收这些参数,请修改回调函数将接受的参数,如下所示:
function wporg_custom( $post_id, $post ) {
// do something
}
过滤器filters
过滤器
过滤器是两种类型的Hook之一。
它们为函数提供了一种在 WordPress 核心、插件和主题执行期间修改数据的方法。它们与Actions相对应。
与Actions不同,过滤器旨在以隔离的方式工作,并且永远不应该产生副作用,例如影响全局变量和输出。过滤器期望有一些东西返回给他们。
添加过滤器
添加过滤器的过程包括两个步骤。
首先,您需要创建一个回调函数,该函数将在过滤器运行时调用。其次,您需要将回调函数添加到一个钩子中,该钩子将执行函数的调用。
您将使用add_filter() 函数,并传递至少两个参数:
string $hook_name
这是您要连接的过滤器的名称,并且callable $callback
您的回调函数的名称。
下面的示例将在the_title
执行过滤器时运行。
function wporg_filter_title( $title ) {
return 'The ' . $title . ' was filtered';
}
add_filter( 'the_title', 'wporg_filter_title' );
假设我们有一个帖子标题“学习 WordPress”,上面的示例将其修改为“学习 WordPress 已被过滤”。
您可以参考Hooks章节来获取可用钩子的列表。
随着您获得更多经验,查看 WordPress 核心源代码将使您找到最合适的挂钩。
附加参数
add_filter() 可以接受两个附加参数,int $priority
用于指定回调函数的优先级,以及int $accepted_args
将传递给回调函数的参数数量。
例子
要在满足特定条件时向标记添加 CSS 类:
function wporg_css_body_class( $classes ) {
if ( ! is_admin() ) {
$classes[] = 'wporg-is-awesome';
}
return $classes;
}
add_filter( 'body_class', 'wporg_css_body_class' );
定制挂钩
一个重要但经常被忽视的做法是在插件中使用自定义挂钩,以便其他开发人员可以扩展和修改它。
自定义挂钩的创建和调用方式与 WordPress 核心挂钩相同。
创建一个钩子
要创建自定义挂钩,请使用do_action()
for Actions和apply_filters()
for Filters。
这使得插件更容易根据用户的需求进行修改。
添加回调到钩子
要将回调函数添加到自定义挂钩,请使用add_action()
for Actions和add_filter()
for Filters。
命名冲突
当两个开发人员将相同的钩子名称用于完全不同的目的时,就会发生命名冲突(“冲突”)。这导致很难发现错误。因此,在钩子名称前添加一个唯一的字符串是很重要的,以避免钩子名称与其他插件发生冲突。
例如,名为的过滤器email_body
足够通用,两个或多个开发人员可以在不同的插件中出于不同的目的使用此钩子。所以为了避免这种情况,添加了一个前缀。例如,本手册中用作示例的函数使用wporg_
作为前缀。
当你选择你的前缀时,你可以使用你的公司名称、你的 wp 句柄、插件名称,任何你真正喜欢的东西。我们的目标是使其独一无二,因此请明智地选择。
例子
可扩展操作:设置表单
如果您的插件将设置表单添加到管理面板,您可以使用操作来允许其他插件向其中添加自己的设置。
do_action( 'wporg_after_settings_page_html' );
现在另一个插件可以为钩子注册回调函数wporg_after_settings_page_html
并注入新设置:
add_action( 'wporg_after_settings_page_html', 'myprefix_add_settings' );
请注意,因为这是一个操作,所以不会返回任何值。另请注意,由于未指定优先级,因此它将以默认优先级 10 运行。
可扩展过滤器:自定义帖子类型
在此示例中,当注册新的帖子类型时,定义它的参数将通过过滤器传递,因此另一个插件可以在创建帖子类型之前更改它们。
function wporg_create_post_type() {
$post_type_params = [/* ... */];
register_post_type(
'post_type_slug',
apply_filters( 'wporg_post_type_params', $post_type_params )
);
}
现在另一个插件可以为钩子注册回调函数wporg_post_type_params
并更改帖子类型参数:
function myprefix_change_post_type_params( $post_type_params ) {
$post_type_params['hierarchical'] = true;
return $post_type_params;
}
add_filter( 'wporg_post_type_params', 'myprefix_change_post_type_params' );
请注意,过滤器会获取数据、修改数据并返回数据。因此,名为 ( ) 的代码myprefix_change_post_type_params
不会使用 echo 或 html 或直接将任何其他内容输出到屏幕。另请注意,返回的值将直接使用,而register_post_type
无需先分配给变量。这很容易跳过额外的(不必要的)步骤。
另请注意,由于未指定优先级,因此它将以默认优先级 10 运行。并且由于没有预期参数数量的值,因此假定默认值为 1。
高级主题
删除操作和过滤器
有时您想从另一个插件、主题甚至 WordPress Core 已注册的挂钩中删除回调函数。
要从挂钩中删除回调函数,您需要调用remove_action()
或 remove_filter()
,具体取决于回调函数是作为操作还是过滤器添加。
remove_action()
传递给/ 的参数 必须与传递给/注册它的remove_filter()
参数相同,否则删除将不起作用。add_action()
add_filter()
例子
假设我们希望通过删除不必要的功能来提高大型主题的性能。
让我们通过查看 来分析主题的代码functions.php
。
function wporg_setup_slider() {
// ...
}
add_action( 'template_redirect', 'wporg_setup_slider', 9 );
该wporg_setup_slider
函数正在添加一个我们不需要的滑块,它可能会加载一个巨大的 CSS 文件,然后加载一个 JavaScript 初始化文件,该文件使用大小为 1MB 的自定义编写库。我们可以摆脱它。
wporg_setup_slider
由于我们希望在注册(执行)回调函数后挂钩 WordPress,因此functions.php
最好的机会就是after_setup_theme
挂钩。
function wporg_disable_slider() {
// Make sure all parameters match the add_action() call exactly.
remove_action( 'template_redirect', 'wporg_setup_slider', 9 );
}
// Make sure we call remove_action() after add_action() has been called.
add_action( 'after_setup_theme', 'wporg_disable_slider' );
删除所有回调
remove_all_actions()
您还可以使用/删除与挂钩关联的所有回调函数remove_all_filters()
。
确定当前钩子
有时您想要在多个钩子上运行一个操作或一个过滤器,但根据当前调用它的钩子而表现不同。
您可以使用 current_action()
/current_filter()
来确定当前的操作/过滤器。
function wporg_modify_content( $content ) {
switch ( current_filter() ) {
case 'the_content':
// Do something.
break;
case 'the_excerpt':
// Do something.
break;
}
return $content;
}
add_filter( 'the_content', 'wporg_modify_content' );
add_filter( 'the_excerpt', 'wporg_modify_content' );
检查钩子运行了多少次
有些钩子在执行过程中会被多次调用,但您可能只希望回调函数运行一次。
在这种情况下,您可以使用did_action()检查钩子运行了多少次。
function wporg_custom() {
// If save_post has been run more than once, skip the rest of the code.
if ( did_action( 'save_post' ) !== 1 ) {
return;
}
// ...
}
add_action( 'save_post', 'wporg_custom' );
使用“all”Hook 进行调试
如果您希望在每个钩子上触发回调函数,则可以将其注册到该all
钩子。有时,这在调试情况下很有用,可以帮助确定特定事件何时发生或页面何时崩溃。
function wporg_debug() {
echo '<p>' . current_action() . '</p>';
}
add_action( 'all', 'wporg_debug' );