我希望主题能够改变插件类中的默认数据数组。目前的设置如下:
namespace Example;
class Example_Class {
private $stuff;
public function __construct() {
$this->stuff = $this->set_stuff();
}
public function set_stuff() {
$things = array(
\'first\' => \'First\',
\'second\' => \'Second\',
);
return apply_filters( \'my_cool_filter\', $things );
}
}
然后为了测试它,我把它放在主题的函数中。php:
function change_things( $things ) {
$things = array(
\'third\' => \'Third\',
\'fourth\' => \'Fourth\',
);
return $things;
}
add_filter( \'my_cool_filter\', \'change_things\' );
但是它不起作用。这个
$stuff
属性仍设置为原始默认数组,因此
add_filter()
没有任何效果。看起来是的
the same question as this, 但我看不出我做错了什么。
编辑:该类位于插件中,并作为插件加载的一部分进行实例化-从主插件文件调用。类中的方法管理设置,使用该属性的主方法连接到admin_init
, 但如果我加上die( var_dump( $this->stuff ) )
在构造器中,设置完之后,我得到的是原始数组,而不是过滤后的数组。我想从大家的说法中可以清楚地看出,这一定是因为事情发生的顺序不对,但插件不是总是在主题之前加载吗?
最合适的回答,由SO网友:Sally CJ 整理而成
Your code is good — you are using both apply_filters()
and add_filter()
correctly.
But the timing/hook does not seem correct.
I think it\'s clear from what everyone is saying that it must be an issue of things happening in the wrong order, but don\'t plugins always load before the theme?
Wrong order: Yes — you most likely called apply_filters()
before the filter (change_things()
) is added (via add_filter()
) or that you instantiated the class Example_Class
in the wrong place/hook (i.e. instantiated too early).
Don\'t plugins always load before the theme? Yes they do, therefore you need to ensure your filter is added on-time — and the earliest hook you\'d use to ensure your code runs after the theme is loaded would be after_setup_theme
:
/**
* Fires after the theme is loaded.
*
* @since 3.0.0
*/
do_action( \'after_setup_theme\' );
See this Codex article for a list of the hooks and their order of execution on a WordPress page, both admin and non-admin sides, but for an up-to-date list, try Query Monitor or the other options here.
So for example, if you instantiated the class in plugins_loaded
, then the property Example_Class::$stuff
would not be filtered by the change_things()
.
And here are two examples demonstrating how should and should not the class be instantiated:
On-time/good instantiation — admin_init
runs after after_setup_theme
:
// In main plugin file:
// Note: I used closure merely for testing purposes.
add_action( \'admin_init\', function () {
require_once \'/path/to/class-example-class.php\';
new Example\\Example_Class;
// the $this->stuff in the class would now be the $things returned by
// change_things()
} );
And as you may have guessed it, you can use after_setup_theme
in place of the admin_init
. But in most plugins, they initialize things via the init
hook which runs after WordPress setups things like the theme and current user:
/**
* Fires after WordPress has finished loading but before any headers are sent.
*
* Most of WP is loaded at this stage, and the user is authenticated. WP continues
* to load on the {@see \'init\'} hook that follows (e.g. widgets), and many plugins instantiate
* themselves on it for all sorts of reasons (e.g. they need a user, a taxonomy, etc.).
*
* If you wish to plug an action once WP is loaded, use the {@see \'wp_loaded\'} hook below.
*
* @since 1.5.0
*/
do_action( \'init\' );
Too-early instantiation — plugins_loaded
runs before after_setup_theme
:
// In main plugin file:
add_action( \'plugins_loaded\', function () {
require_once \'/path/to/class-example-class.php\';
new Example\\Example_Class;
// change_things() was not executed
} );