WordPress 过滤器主要作用是在数据输出或存储之前进行拦截修改。主要过程如下:
function A () {
1:执行代码
2:获得数据
3:触发钩子
4:执行挂在钩子上的函数
5:返回修改后数据
6:继续执行代码
}
1:注册过滤器
需要三个准备条件:钩子名称、执行函数、执行顺序。
// 注册三个回调函数到 'my_custom_filter' 钩子
add_filter( 'my_custom_filter', 'callback1', 10 );
add_filter( 'my_custom_filter', 'callback2', 20 );
add_filter( 'my_custom_filter', 'callback3', 30 );
如上代码,my_custom_filter是钩子名称,callback1是执行函数,10 是执行顺序。细看add_filter功能,该功能在文件:wp-includes/plugin.php
function add_filter( $hook_name, $callback, $priority = 10, $accepted_args = 1 ) {
global $wp_filter;
// 确保钩子数组存在
if ( ! isset( $wp_filter[ $hook_name ] ) ) {
$wp_filter[ $hook_name ] = new WP_Hook();
}
// 调用 WP_Hook 对象的 add() 方法
$wp_filter[ $hook_name ]->add_filter( $hook_name, $callback, $priority, $accepted_args );
return true;
}
有个全局数组$wp_filter,该数组专门保存一个个钩子对象WP_Hook。注册过滤器时,先判断是否已有存在的钩子对象,没有则直接新建对象。该对象也有一个add_filter方法,注册过滤器时就是调用该方法。
钩子对象WP_Hook钩子对象里有个属性字段callbacks,也是以数组形式存在。字段属性callbacks数组结构如下:
array(
10 => array(
'callback1' => array(
'function' => 'callback1',
'accepted_args' => 1
)
),
20 => array(
'callback2' => array(
'function' => 'callback2',
'accepted_args' => 1
)
),
30 => array(
'callback3' => array(
'function' => 'callback3',
'accepted_args' => 1
)
)
)
还有一种数组结构,允许存在相同的执行顺序的基础上,支持绑定多个执行函数,如下:
array(
10 => array(
'callback1' => array( /* 回调1 */ ),
'callback2' => array( /* 回调2 */ ), // 同一优先级的多个回调
),
20 => array(
'callback3' => array( /* 回调3 */ ),
),
// ...
)
以上callbacks数组数据就来于自己的钩子对象WP_Hook的add_filter方法,该方法主要功能就是把新注册的过滤器,按照既定排序规则增添至该对象callbacks属性数组中。
2:触发执行过滤器。
function A () {
执行代码...
// 得到数组
$initial_value = '原始内容';
// 执行过滤器
$final_value = apply_filters( 'my_custom_filter', $initial_value );
// 输出结果:[ 原始内容 被 callback1 修改 被 CALLBACK2 修改 ]
echo $final_value;
}
my_custom_filter是钩子名称,$initial_value是要修改的数据。apply_filters是全局函数,也在wp-includes/plugin.php文件中
function apply_filters( $tag, $value, ...$args ) {
global $wp_filter;
// $wp_filter 是一个数组,存储所有钩子及其对应的 WP_Hook 对象
if ( isset( $wp_filter[ $tag ] ) ) {
// 将 $value 和 $args 组合成参数数组
$args = array_merge( [ $value ], $args );
// 调用对应钩子的 WP_Hook 对象的 apply_filters 方法
return $wp_filter[ $tag ]->apply_filters( $value, $args );
}
return $value;
}
同样的,该钩子对象WP_Hook也有一个add_filter方法,执行过滤器时就是调用该方法。如下:
// WP_Hook 类的方法(WordPress 内部实现)
class WP_Hook {
public function apply_filters( $value, $args ) {
// 遍历所有注册到这个钩子的回调函数
foreach ( $this->callbacks as $priority => $callbacks ) {
foreach ( $callbacks as $callback ) {
// 调用回调函数并传递参数
$value = call_user_func_array( $callback, $args );
}
}
return $value;
}
}
其实就是对自己的钩子对象WP_Hook的callbacks数组数据进行遍历,逐一执行里面存储的函数。call_user_func_array( $callback, $args ),其中$callback是执行函数。$args是数组参数,数组中的第一个数据就是要修改的数据。循环执行函数如下:
function callback1( $value ) {
return $value . ' 被 callback1 修改';
}
function callback2( $value ) {
return strtoupper( $value );
}
function callback3( $value ) {
return '[' . $value . ']';
}
每执行一个函数完,返回修改后的值,再次循环并将参数继续传入下一个执行函数以继续操作数据。直至把$callback数组里的所有函数执行完毕。最终$value值返回给业务代码function A ()中的$initial_value值。至此过滤器功能作用结束。