我面临着一个问题,我似乎不能弄清楚。
我有一个插件,它有过滤器,让你改变修改它的一些数据。
我在插件中有一个简单的类方法:
public static function getAllowedColors(){
$colors = array(
'green',
'blue',
);
return apply_filters('my_allowed_colors', $colors);
}
这个方法在整个插件中使用,就像这个Colors::getAllowedColors()
,但是它应该是可过滤的,这样第三方插件或开发人员就可以改变它。
问题是,我创建并激活了一个小的自定义插件,它没有任何类或任何东西..只是主插件文件与所需的插件头文件,在该文件中,我做了通常的:
function add_allowed_color($colors){
$colors[] = 'black';
return $colors;
}
add_filter('my_allowed_colors', 'add_allowed_color');
由于某种原因,当getAllowedColors()
被调用时,新颜色永远不会被添加。
我在getAllowedColors()
方法中添加了一个dump语句,然后在小的自定义插件主插件文件(其中存在add_filter)中添加了一个dump语句,我可以看到getAllowedColors
在小的自定义插件之前被调用。
我知道add_filter
需要在apply_filters
之前启动,这样你的修改才能生效.但我不知道如何确保我的小自定义插件总是在主插件及其所有类和功能之前运行。
我偶然发现了一个类似问题的答案:https://stackoverflow.com/a/19279650/4484799,但它在这种情况下不适用,因为getAllowedColors()
是一个实用程序方法,在整个插件中需要时会被调用。
在小的自定义插件中,我也尝试调整代码如下:
add_action('after_setup_theme', function(){
function add_allowed_color($colors){
$colors[] = 'black';
return $colors;
}
add_filter('my_allowed_colors', 'add_allowed_color');
});
虽然这是有效的PHP,如果我在其定义的底部调用add_allowed_color('test')
,它会返回test
,但过滤器仍然不起作用。
我想知道如何使用这个过滤器。是什么阻止它工作?我之前在几个不同的插件之间使用过几次add_filter
,特别是WooCommerce,它有很多过滤器,但我不知道为什么它不起作用。
如有任何帮助,我们将不胜感激
2条答案
按热度按时间nqwrtyyt1#
我先说一些你们已经知道的事情:WordPress是由钩子扩展的。
正如我所说,我知道你知道这一点,但我会进一步澄清它说:WordPress应该只通过钩子扩展。
我的意思是,任何代码不运行在一个钩子也不应该假设WordPress的状态。
根据OP的评论,他们有一个单例或控制器或类似的东西,当他们的插件入口文件被执行时启动。这是一个非常常见的插件模式,它本身并不一定是正确或错误的,只要这段代码只做PHP的事情,如示例化类,注册自动加载器或创建全局函数,或注册WordPress操作/过滤器。如果这段代码做了任何其他特定于WordPress的事情,那就是麻烦的地方。
麻烦的原因是你不能保证其他插件已经加载,并且绝对可以肯定主题也没有加载。因为这些还没有加载,他们还没有机会注册他们的过滤器。
即使像
get_option
这样简单的函数,在其生命周期中也至少有六个钩子可以调用,而简单的翻译函数__
有两个钩子。此外,像get_home_url
这样的“简单”函数仍然在后台调用get_option
。在钩子之外使用这些函数中的任何一个都可能导致意外的结果。作为一个开发人员,它确实有助于理解加载顺序,至少是一个高层次的:
1.空投已经装好了
1.更多WordPress loading including database
1.必须使用的插件已加载
1.已加载活动插件
1.主题已加载
1.用户被认证
对于该列表中的最后四个中的每一个,一旦完成该特定步骤,也有相应的钩子:
muplugins_loaded
plugins_loaded
after_setup_theme
init
如果你运行的代码在相应的钩子运行之前以任何方式与WordPress交互(除了过滤器),你应该假设该级别的其他代码还没有运行。例如,如果您正在编写一个在入口处执行代码的插件,这意味着
plugins_loaded
,after_setup_theme
和init
尚未运行,并且其他插件和主题完全可能没有注册任何钩子。类似地,如果你的插件在plugins_loaded
加载的钩子中运行代码,那么应该假设主题还没有被引导,所以它还没有注册任何钩子。注意:插件不应该注册
muplugins_loaded
钩子,主题也不应该注册plugins_loaded
钩子,因为注册时钩子已经运行了。我在开发人员的代码中确实看到过几次这种情况。tl;dr
除非你需要更具体的东西,否则插件中的绝大多数代码都可以通过
init
钩子调用,因为此时WordPress的大部分内容已经加载。此外,通常没有优势创建你的单例“迟早”。然而,如果你的单例是完成所有额外钩子注册的单例(我看到的另一种常见模式),那么移动代码可能是值得的,这样单例只能被需要它的代码用于它的示例方法。
编辑
我会修改这一点说,有时事情似乎取决于插件加载顺序,这通常是字母顺序。
如果你有插件 A 和 B,并且插件 A 恰好在 B 之前加载,那么它将能够在 B 需要它们之前注册它的钩子。
然而,这只能被认为是巧合。插件的加载顺序实际上是可以改变的,或者你或其他插件作者可能会在某一天重新命名你的插件。
sqyvllje2#
@ChrisHaas是对的。在你的小的自定义插件中,从一个“plugins_loaded”操作处理程序添加你的过滤器,而不是你使用的那个。“plugins_loaded”在所有插件都被初始化之前不会触发。