WordPress如何确保插件同时运行,以及如何解决一个插件对另一个插件的依赖?

时间:2018-07-30 作者:coolpasta

假设我有一个插件plugin_1_action 当它初始化时。

现在,因为我想扩展这个插件,我将plugin_1_action, 但如果我的插件是在那个插件之后安装的呢?这个插件不会先运行吗?因此,我将失去抓住plugin_1_action

不管怎样,我都可以挂接,比如说,Woo的动作,Woo也可以挂接我的动作,这对我来说是很奇怪和神奇的,即使很明显我的插件安装得比它晚。

即使大多数插件在init 钩子(因此它们在相同的空间上执行),它们的优先级设置仍然不同。这意味着plugin1的代码将在plugin2的代码之前运行,如果plugin2在plugin1中有一个钩子,那么,真倒霉。。。或者没有,显然WordPress没有这个问题。

它是如何工作的?

2 个回复
SO网友:Jacob Peattie

如果插件确实运行plugin_1_action 一旦加载,意味着do_action() 调用只是位于插件文件中,而不是位于稍后挂接的函数中,那么是的,您是正确的:如果插件稍后加载,您将无法挂接到它。

但插件的工作方式几乎从来都不是这样。几乎所有插件都不会在加载后立即运行任何代码。插件通常会将其所有功能挂接到以后,通常不早于init 钩子,在加载所有插件和主题后运行。

假设原始插件有以下代码:

function og_plugin_initialize() {
    // Does stuff.

    do_action( \'og_plugin_initialized\' );
}
此代码可能会挂接在上运行init 挂钩:

add_action( \'init\', \'og_plugin_initialize\', 20 );
所以og_plugin_initialized 直到init 挂钩,优先级为20。

如果您有一个想要挂接到og_plugin_initialized 钩子,然后将其添加到插件中,如下所示:

function my_plugin_init() {
    // Do stuff.
}
add_action( \'og_plugin_initialized\', \'my_plugin_init\' );
当这样做时,插件加载的顺序无关紧要,因为插件和队列都将其函数排队等待稍后运行。由于这两个函数都将在加载所有插件后运行,因此您可以使用原始插件中定义的函数,而不会产生问题。

SO网友:Tom J Nowell

Important: 将动作和挂钩视为事件

这种思维模式会更好地为你服务。

现在,因为我想扩展那个插件,我将挂接到plugin\\u 1\\u操作,但如果我的插件是在那个插件之后安装的呢?

你可以按你想要的任何顺序安装你的插件,不管它们的加载顺序如何,都是一样的。首先安装插件C并不意味着它的代码首先运行。

插件是按字母顺序加载的,所以插件a 将在插件之前加载b 因为A在B之前,等等

那个插件不会先运行吗?这样,我就失去了抓住plugin\\u 1\\u动作挂钩的机会了?

正确,如果操作触发一次,并且该事件已经发生,则为时已晚。您仍然可以钩住它,但该事件已经发生,因此它将永远不会运行。

类似于告诉某人在去商店之后而不是之前购买牛奶。你可以这样做,但除非他们第二次去商店,否则它不会给你牛奶。

要让它继续工作,需要涉及某种时间旅行/时间机制。Dr-Who可能能够做到这一点,但我们需要重构来修复原始插件。

对我来说,这很奇怪,也很神奇,不管怎样,我都能勾引,比如说,吴的行为,而吴可以勾引我的行为,

行动只是行动,不属于任何人。代码没有沙箱,一旦加载就可以加载。插件代码与WP核心和其他插件共享所有相同的空间。

即使很明显我的插件安装得比它晚。

安装顺序无关。正如我们之前所了解到的,执行顺序很重要,一旦触发事件/操作/挂钩,您仍然可以钩住它,但您的函数在再次触发之前不会运行,这可能永远不会发生。WP挂钩不做时间旅行。

即使大多数插件在init钩子上运行(因此它们在相同的空间上执行),它们的优先级设置仍然不同。

实际上,如果事件尚未发生,则可以指示优先级以影响调用函数的顺序。

这意味着plugin1的代码将在plugin2的代码之前运行,如果plugin2在plugin1中有一个钩子,那么,真倒霉。。。或者没有,显然WordPress没有这个问题。

哦,但确实如此!正如我前面提到的,您可以向已经触发的钩子添加函数,这并不意味着它可以追溯到钩子先前触发的时间。正如我之前提到的,这需要时间旅行技术。

这里的根本问题是插件在initadmin_init 挂钩发生了。当插件加载时,他们应该设置对象,添加挂钩等,但他们不应该这样做。这就是生命周期事件init etc用于

结束