WordPress过滤钩子函数add_filter()、apply_filters()源码解析

WordPress过滤器(过滤钩子)

过滤器概念:它是一类函数,在WP执行和传递数据过程中,它可以实现在完成某一动作(如输出到浏览器或写入数据库等)之前对数据进行过滤再处理的目的。

过滤器原理:它主要利用一个全局变量$wp_filter,增加过滤函数时使用add_filter()函数给全局变量$wp_filter增加了一个数组元素,这个值存储了钩子名、对应函数及执行优先级等信息,在调用apply_filters()函数使用过滤器时,它通过循环查找出所有跟钩子关联的函数并将其依次作用于待处理的数据上,最后返回处理后的数据。

 

过滤器使用步骤

由于PHP代码会经过Zend等引擎翻译,代码中步骤的先后顺序并不重要,所以以下步骤仅为便于理解钩子原理的伪步骤,不具有实际参考意义!

1、创建钩子(可省略):使用apply_filters()函数可以创建一个没有挂载函数的钩子,挂载函数可以通过add_filter()添加,最后再使用apply_filters()调用执行;

2、创建过滤函数:它需要有传入参数即待处理数据(一般为一个参数,也可多个参数),其他与创建普通函数没有任何区别,函数的作用一般用于对传入数据进行处理;

3、挂载函数:即使用add_filter()将函数挂载到指定钩子上;

4、执行过滤器:使用apply_filters()可以依次执行挂载在指定钩子上的所有函数以处理传入数据,最后返回处理后的数据;

 

过滤函数详解及源码分析:

1、add_filter($tag,$function_to_add,$priority = 10,$accepted_args = 1)

add_filter()作用:该函数用于给指定的过滤钩子$tag添加指定的挂载函数$function_to_add,同时它可以确定挂载函数执行优先级及其可接收参数个数;

add_filter()参数说明

$tag为钩子名;

$function_to_add为挂载函数名;

可选参数$priority为该挂载函数执行的优先级,默认为10,该数字越小则越早执行,数字相同则按其添加到钩子上的顺序执行,越早添加越早执行;

可选参数$accepted_args确定挂载函数接收的参数个数,默认为1;

add_filter()源码分析:

_wp_filter_build_unique_id()源码分析:

该函数可创建一个供存储和检索的唯一值。

2、apply_filters($tag, $value)

apply_filters()作用:该函数调用挂载在过滤钩子$tag上的所有挂载函数依然以$value为传入参数递归式处理数据,最后返回经所有挂载函数处理过的值;

apply_filters()参数说明:

$tag为钩子名;

$value为过滤钩子上挂载函数的传入参数;

apply_filters()源码分析:

解析1:如果$wp_filter数组中有名为all的钩子则调用PHP函数func_get_args()来获取当前函数所有参数组成的数组,获取参数后通过_wp_call_all_hook()函数调用钩子名为all的所有filter,关于该函数的源码分析见下文;

解析2:这段代码主要用于对$wp_filter[$tag]根据键名(主要为函数优先级等数字)排序,以得到一个过滤函数(挂载函数)的执行先后顺序的排序,而$merged_filters变量主要用于判断是否需要重新对数组进行排序,若没有新增函数等,则if判断false不再重新排序,若新增了函数则由于
add_filter()函数中有代码unset( $merged_filters[ $tag ] ),所以isset()函数为判断为false而整个if则判断为true,然后执行重新排序函数。这样做可以节省服务器CPU资源,有利于程序优化。

解析3:这段代码就是该函数的精髓了,首先将当前钩子的值(包括过滤函数名和其参数个数)赋给数组$the_,然后通过循环将钩子上所有的过滤函数一个个执行,并且每个函数执行后得到的值会借助参数$args传递给下一个函数,直到所有函数执行完成,最后将这个钩子名弹出“当前钩子”队列并返回最后得到的值;其中,call_user_func_array(func,arg)为PHP函数,主要用于把参数值arg传递给函数func去执行;array_slice(args,star,length)也是PHP函数,主要用于返回数组args中从star开始的length个值,在本代码中,若apply_filters()函数仅接受一个参数值,就相当于把这一个值传给过滤函数,若有两个参数则,则会把这两个值都传给过滤函数;

_wp_call_all_hook()源码分析:

该函数调用名为all的钩子并执行挂载在其上的所有函数;

从apply_filter()源码可以看到当有名为all的钩子存在时,$args获取了当前钩子名和要处理的值,而本函数将这这些参数都放入名为all的钩子上挂载的函数进行处理。至于名为all的钩子是否存在,以及该钩子上挂载了什么函数,我就不知道了

微信公众号
手机浏览(小程序)
0
分享到:
没有账号? 忘记密码?