如何解决 WordPress 插件加载顺序和相互之间依赖问题

2023-04-13 10:20:28 浏览数 (1)

如果你和我一样如果写了30多个插件,以后还会有更多的插件,肯定会和我一样存在插件的加载顺序和插件之间的依赖问题,那么我是怎么解决的呢?

基于 WPJAM Basic?

经常看我博客和公众号的同学都知道,我所有插件都是基于 WPJAM Basic 插件的,那么我首先要解决的问题就是判断 WPJAM Basic 是否已经加载,有两种方法,

首先介绍第一种方法,我们可以通过函数 is_plugin_active( $plugin ) 判断某个插件是否已经激活了,所以判断 WPJAM Basic 是否激活的代码:

代码语言:javascript复制
is_plugin_active('wpjam-basic/wpjam-basic.php');

但是这个函数目前只是 WordPress 后台可用,如果需要在前台使用,还需要自己手动加载文件:

代码语言:javascript复制
require_once ABSPATH . 'wp-admin/includes/plugin.php';

所以这个方法有点麻烦,也不是最佳实践。

使用到了第二种方法,使用 WordPress Action Hook 接口。首先在 WPJAM Basic 插件的最后自定义一个 action:

代码语言:javascript复制
do_action('wpjam_loaded');

然后其他函数通过函数 did_action 判断该 action 执行了才加载和执行具体的代码。

代码语言:javascript复制
if(did_action('wpjam_loaded')){
	// 加载具体的代码
}

但是这样的方式有个问题,WordPress 插件加载是基于文件名顺序的,所以比如微信插件(weixin-robot-advanced)是优先 WPJAM Basic(wpjam-basic)加载的,那么怎么办?

这个时候直接上面的代码判断,肯定是无效的,我们应该等到所有插件文件加载之后再去判断:

代码语言:javascript复制
add_action('plugins_loaded', function(){
	if(did_action('wpjam_loaded')){
		// 加载具体的代码
	}
}

插件之间的依赖?

上面的方法完美的处理了其他插件基于 WPJAM Basic 的模式,但是如果其他插件之间也有依赖关系,我们怎么处理,举个例子,比如我最近写的表单插件是基于评论增强插件。

首先评论增强插件也有一个自定义的 action:wpjam_comment_loaded

因为表单插件和评论增强插件都是基于 WPJAM Basic,所以他们具体的代码都是在 plugins_loaded,所以他们之间具体是谁被执行并不确定的。

如果评论插件先执行:

代码语言:javascript复制
add_action('plugins_loaded', function(){
	if(did_action('wpjam_loaded') && did('wpjam_comment_loaded')){
		// 加载表单插件的代码
	}
}

如果是表单插件先执行:

代码语言:javascript复制
add_action('plugins_loaded', function(){
	if(did_action('wpjam_loaded')){
		add_action('wpjam_comment_loaded', function(){
			// 加载表单插件的代码
		});
	}
}

整合一下,就可以完美解决插件之间的依赖关系:

代码语言:javascript复制
add_action('plugins_loaded', function(){
	if(did_action('wpjam_loaded')){	// WPJAM Basic 插件已执行
		function wpjam_form_load(){
			// 加载表单插件的代码
		}

		if(did_action('wpjam_comment_loaded')){	// 评论增强插件已执行
			wpjam_form_load();
		}else{
			// 评论增强插件执行的时候再加载
			add_action('wpjam_comment_loaded', 'wpjam_form_load');
		}
	}
}

如果每次都要这样处理有点繁琐,并且这些插件都是基于 WPJAM Basic 的,所以我在 WPJAM Basic 中增加了 wpjam_load 函数来处理插件依赖问题:

代码语言:javascript复制
function wpjam_load($hook, $callback){
	if(did_action($hook)){
		call_user_func($callback);
	}else{
		add_action($hook, $callback);
	}
}

然后最终的代码简化为:

代码语言:javascript复制
add_action('plugins_loaded', function(){
	if(did_action('wpjam_loaded')){
		wpjam_load('wpjam_comment_loaded', function(){
			// 加载表单插件的代码
		});
	}
}

当然除此之外, wpjam_load 还可以帮忙处理其他问题,比如某个函数需要在 init 的 action 之后执行即可:

代码语言:javascript复制
wpjam_load('init', function(){
	// 具体代码代码
});

0 人点赞