依赖另一个插件的可靠方式是什么?

时间:2020-05-19 作者:Daniel Simmons

目前,我的做法是plugins_loaded hook,我让全世界都知道我的插件已经加载了:

add_action( \'plugins_loaded\', function() {
    do_action( \'my_plugin_has_loaded\' );
}, 10 );
因此,其他人可以依赖/仅在以下情况下运行my_plugin_has_loaded 火,但是,我看到很多钩子plugin_loaded (5.1.0)甚至一些plugins firing their init before plugins_loaded. 有没有更好的方法让一个插件等待另一个插件?

我发现这种方法的问题是,我在上启动了自己的initplugins_loaded, 然而,我也看到了一线希望——插件应该在这里加载,所以,如果有任何类型的逻辑像这样,它应该在这里。

问题1-使用class_exists:

我不能像对待动作那样强制使用命名约定,例如始终查找/挂起plugin-$name%:init 通过行动确保一致性。如果我知道一个插件的名称,那么我可以很容易地预测它的初始点,这样我就可以运行它,但是如果我不知道,我必须知道它的主控制器是什么类,这将引导我进入下一个点-,如果我依靠这种检查方法,I am merely looking for the existence of a class, which, at best, lets me know a plugin is activated, but not if the plugin has finished its setup. 通过一个动作,我可以任意决定插件何时完成加载和初始化所需的所有内容,以便从属插件可以运行。

从(2)开始,我现在强迫自己以这样一种方式编写插件,我总是需要一个运行所有东西的上帝模式控制器类__construct. 愿意这样做的人class_exists( \'MyClass\\From\\Plugin\\IWanna\\DependOn\' )也会固有地认为我在__construct, however, my plugin my have errors in initializing itself, but, because it\'s all run on __cosntruct, I can\'t debug that.

第2期-使用TGMPA:

假定插件A 依赖于插件B. 如果用户禁用B, 然后A 将抛出错误。当然,我可以处理它们,但这正是问题的关键所在,真的-扭转我刚才说的这一点,你就会遇到我的问题:在处理与插件交互的每一种情况时确保依赖性。我需要这是完全脱离用户的土地领土

3 个回复
SO网友:Mort 1305

考虑插件A:

$A_message;

add_action(\'plugins_loaded\', function() {
    do_action(\'plugin-A:init\');
});

// Hooks allow B to access A (both during initialization of A and elsewhere in WordPress) without having to check if A exists.

add_filter(\'plugin-A:set\', function($msg) {
    $A_message = $msg;
}, PHP_INT_MAX);

add_filter(\'plugin-A:get\', function($msg) {
    return $A_message;
}, PHP_INT_MIN);
现在,考虑插件B:

add_action(\'plugin-A:init\', function() {
    // We\'re 100% sure that A has loaded (if it exists)
    // Store what Cheech says in A.  (Using a filter allows us to not have to check if A exists).
    do_action(\'plugin-A:set\', "Brent! Open the door!");
});

add_filter(\'the_title\', function($title) {
    // Get something from A (and we don\'t have to check if it exists).
    // If A exists, return what Cheech says; if A does not exist, return what Chong says.
    $title = apply_filters(\'plugin-A:get\', "Dave\'s not here, man!");
    return $title;
});
大多数代码听起来对您来说都不是什么新鲜事。加载Foo时,它通过以下方式初始化Bar插件bar_on_plugins_loaded()foo_load_bar(). 这里的新特点是,Foo不需要做任何花哨的检查来查看Bar是否存在。这是因为foo_load_bar() 执行由Bar定义的钩子,而不是Bar本身的属性。(很酷吧?)

稍后在代码中请求标题时(如在帖子列表表中)foo_get_bar_message()bar_get_message() 将通过以下方式返回在条形图初始化期间设置的条形图值bar_set_message(). 同样,这一切都是在无需Foo插件检查Bar是否存在的情况下完成的。并且,如果该条不存在,将返回Foo默认值。(特别感谢Cheech and Chong 获得灵感。)

Edit: 在上面的例子中,B更多地依赖于A,而不是相反。但是,你要求A依赖于B,同样的概念在这里也成立。考虑将此添加到插件A中:

// This function is used somewhere in plugin-A ...
function a_func() {
    // Not sure if B exists, but we can make B do something if it does.
    do_actions(\'plugin-B:some_func\', \'*knock knock knock*\', \'Who Is It?\');
}
这是对插件B的添加:

add_action(\'plugin-B:some_func\', function($cheech, $chong) {
    echo \'<p>\'. $cheech .\'<br>\'. $chong .\'</p>\';
}
除了B(如果存在)将所有标题转换为Dave或Brent的消息外,Cheech和Chong的短剧的开头将由插件A在调用其a_func() 后来在它自己的代码中。根据您的意愿,A不需要做任何事情来检查插件B是否存在。

SO网友:Daniel Simmons

我已经有了这个最初的构建,甚至在问题出现之前就已经成功了。我现在已经看到了@cjbj和Mort的答案。Mort的频率相同,但是,请听我说:

在我的主插件中A, 哪一个B 将取决于,内部index.php:

add_actions( \'plugins_loaded\', function() {
    $boot = (new Init)->boot();

    if( \\is_wp_error( $boot ) ) {
        return False;
    }

    /**
    * Fire if the plugin has successfully loaded itself.
    */
    do_action( \'plugin-A:init\' );
});
内部index.php 插件的B:

add_action( \'plugin-A:init\', function() {
    //Great, so, we\'re 100% sure that A has successfully loaded.
});
我真的找不到任何问题,但是plugins_loaded 闻起来很奇怪。我只是无缘无故地偏执吗?

SO网友:Mohamed Omar

事实上,我使用了一些非常简单的东西,因为我有一个插件,用于多种用途,开发主题/插件,所以我只需在其中定义一个常量(例如\\u常量),然后说我有另一个插件,它依赖于它进行多个操作,可能plugins_loaded 可能没有帮助,所以在插件定义之后,我检查是否定义了该常量,如果没有!?只需终止脚本,然后您将只有插件在插件页面中列出,但就像它是一个全新的空插件一样。一旦依赖的插件处于活动状态,依赖的插件就会正常工作。

类似这样:

<?php
/**
 * Plugin Name: Plugin name
 */

/**
 * Display a notification if one of required plugins is not activated/installed
 */
add_action( \'admin_notices\', function() {
    if (!defined(\'THE_CONSTANT\')) {
        ?>
        <div class="notice notice-error is-dismissible">
            <p><?php esc_html_e( \'Please activate/install {Wanted plugin name} , for this plugin can work properly\' ); ?></p>
        </div>
    <?php }
});


if (!defined("THE_CONSTANT")) return;

相关推荐

Testing Plugins for Multisite

我最近发布了一个WordPress插件,它在单个站点上非常有效。我被告知该插件在多站点安装上不能正常工作,我理解其中的一些原因。我已经更新了代码,现在需要一种方法来测试更新后的代码,然后才能转到实时客户的多站点安装。我有一个用于测试的WordPress安装程序的单站点安装,但需要在多站点安装上进行测试。根据我所能找到的唯一方法是在网络上至少有两个站点来安装整个多站点安装,以测试我的插件。设置WordPress的整个多站点安装是插件开发人员的唯一/首选方式,还是有更快的测试环境可用。