动作和过滤器
Wordpress Hooks
开始使用 WordPress 时经常让开发人员感到困惑的是使用 apply_filters()
和 add_action()
。你会经常看到插件/主题在代码中使用这些插件/主题,如果你不理解这个概念,你会发现很难使用它们。
简而言之(非常简短,详细查看 WordPress 加载流程图的过程),WordPress 按以下方式加载:
- wp-load.php - 函数等
- mu-plugins - 在 mu-plugins 文件夹中找到的任何文件 - 通常用于提供缓存的对象
- 插件 - 没有特定的顺序,任何已安装和激活的插件都将被加载
- 活跃的儿童主题/父主题
- init - 其余数据
- 模板
如果你是开发人员并使用函数文件,则可以看到在过程的早期加载的都比你使用的文件加载的都要多。这意味着你无法修改进程(请注意,你无法覆盖函数)或稍后运行或尚未定义的变量。主题开发人员也可能在其代码中放置钩子以允许插件挂钩或插件可能允许其他插件覆盖其变量。到目前为止,这可能会令人困惑,但请留在那里。
要了解 add_filter()
和 add_action()
,我们需要先了解钩子是如何创建的。
$arga= 'hello';
do_action('im_a_hook', $arga );
当你在 WordPress 中遇到上述内容时,它将调用附加到 hook im_a_hook
的任何函数(查询 $wp_filter
以获取有关该过程的信息)。在你的附加功能中,$arga
将可用于附加功能。
add_action('im_a_hook', 'attached_function');
function attached_function($arga){
echo $arga;
}
这为在加载过程的某些点修改变量提供了强大的新机会。还记得我们之前说过模板是在插件/主题之后加载的吗?一个常见的插件是 WooCommerce,它会在后面的过程中创建屏幕,我不会记录如何在插件中找到 do_action
的示例。
do_action( 'woocommerce_after_add_to_cart_button' );
这里我们创建了一个不传递变量的钩子,但我们仍然可以玩得开心:
add_action( 'woocommerce_after_add_to_cart_button', 'special_offer');
function special_offer(){
echo '<h1>Special Offer!</h1>;
}
上面的 add_action
将是 echo
的特价商品,其中 do_action('woocommerce_after_add_to_cart_button')
位于创建 WooCommerce 屏幕时。所以我们可以使用这个钩子来插入 html。其他用途可能包括完全重定向到不同的屏幕等。
也可以将多个变量传递给函数。在主题函数中试试这个。请注意我们设置为 3 的最后一个参数,因为我们希望使用 3 个可用参数。如果我们将其更改为 2,则只返回 2 并且我们将得到未定义的错误。
add_action('custom_hook', 'attached_function', 10, 3);
function attached_function($a,$b,$c){
var_dump($a);
var_dump($b);
var_dump($c);
}
$arga = 1;
$argb = 2;
$argc = 3;
do_action('custom_hook', $arga, $argb, $argc);
exit;
还有另一种称为过滤器的 WP 钩子类型。过滤器与其使用中的动作不同,动作只能接收变量,显然这些变量都在函数范围内(你应该知道什么是 php 范围,如果不是 google)。过滤器传回返回的数据,因此你可以使用它来修改变量。
$filter_me= apply_filters('im_a_filter', $variable_to_filter);
如果你看到上述内容,则可以修改 $filter_me
的值,因为你返回的任何数据都将是存储在变量中的值。例如(注意我们在示例中将 $variable_to_filter
更改为 $filter_me
):
add_filter('im_a_filter', 'attached_function', 100);
function attached_function($filter_me){
$filter_me= 'ray';
return $filter_me;
}
$filter_me = 'bob';
$filter_me= apply_filters('im_a_filter', $filter_me);
$filter_me
变量现在将包含 ‘ray’ 而不是 ‘bob’ ,我们将优先级设置为 100,因此我们有理由相信没有人在使用后更改值(可以在同一个钩子上运行多个过滤器)所以我们可以现在,如果存在 apply_filters()
,则更改过程中稍后使用的变量。
你也可以传递多个参数,但只能更改一个参数的值。你还必须返回一个值,否则你的变量将不包含任何内容。如果你了解如何使用 php 将值/数组/对象分配给变量,这对你来说是显而易见的,例如:
add_filter('im_a_filter', 'attached_function', 100, 3);
function attached_function($filter_me, $arga, $argb){
$filter_me= 'ray'.$arga.$argb;
$arga= 'you fool';
return $filter_me;
}
$filter_me = 'bob';
$arga = ' middlename';
$argb = ' surname';
$filter_me= apply_filters('im_a_filter', $filter_me, $arga, $argb);
$filter_me
变量现在包含 ‘ray middlename surname’ 。但是什么关于 $arga
?这仍然包含 ‘middlename’ ,在我们的函数中将 $arga
更改为 ‘you fool’ 对其范围之外的定义值没有影响(有方法,谷歌全局等)