如何解决 WordPress 插件加载顺序和相互之间依赖问题
如果你和我一样如果写了30多个插件,以后还会有更多的插件,肯定会和我一样存在插件的加载顺序和插件之间的依赖问题,那么我是怎么解决的呢?
基于 WPJAM Basic?
经常看我博客和公众号的同学都知道,我所有插件都是基于 WPJAM Basic 插件的,那么我首先要解决的问题就是判断 WPJAM Basic 是否已经加载,有两种方法,
首先介绍第一种方法,我们可以通过函数 is_plugin_active( $plugin )
判断某个插件是否已经激活了,所以判断 WPJAM Basic 是否激活的代码:
is_plugin_active('wpjam-basic/wpjam-basic.php');
但是这个函数目前只是 WordPress 后台可用,如果需要在前台使用,还需要自己手动加载文件:
require_once ABSPATH . 'wp-admin/includes/plugin.php';
所以这个方法有点麻烦,也不是最佳实践。
使用到了第二种方法,使用 WordPress Action Hook 接口。首先在 WPJAM Basic 插件的最后自定义一个 action:
do_action('wpjam_loaded');
然后其他函数通过函数 did_action
判断该 action 执行了才加载和执行具体的代码。
if(did_action('wpjam_loaded')){
// 加载具体的代码
}
但是这样的方式有个问题,WordPress 插件加载是基于文件名顺序的,所以比如微信插件(weixin-robot-advanced)是优先 WPJAM Basic(wpjam-basic)加载的,那么怎么办?
这个时候直接上面的代码判断,肯定是无效的,我们应该等到所有插件文件加载之后再去判断:
add_action('plugins_loaded', function(){
if(did_action('wpjam_loaded')){
// 加载具体的代码
}
}
插件之间的依赖?
上面的方法完美的处理了其他插件基于 WPJAM Basic 的模式,但是如果其他插件之间也有依赖关系,我们怎么处理,举个例子,比如我最近写的表单插件是基于评论增强插件。
首先评论增强插件也有一个自定义的 action:wpjam_comment_loaded
。
因为表单插件和评论增强插件都是基于 WPJAM Basic,所以他们具体的代码都是在 plugins_loaded
,所以他们之间具体是谁被执行并不确定的。
如果评论插件先执行:
add_action('plugins_loaded', function(){
if(did_action('wpjam_loaded') && did('wpjam_comment_loaded')){
// 加载表单插件的代码
}
}
如果是表单插件先执行:
add_action('plugins_loaded', function(){
if(did_action('wpjam_loaded')){
add_action('wpjam_comment_loaded', function(){
// 加载表单插件的代码
});
}
}
整合一下,就可以完美解决插件之间的依赖关系:
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
函数来处理插件依赖问题:
function wpjam_load($hook, $callback){
if(did_action($hook)){
call_user_func($callback);
}else{
add_action($hook, $callback);
}
}
然后最终的代码简化为:
add_action('plugins_loaded', function(){
if(did_action('wpjam_loaded')){
wpjam_load('wpjam_comment_loaded', function(){
// 加载表单插件的代码
});
}
}
当然除此之外, wpjam_load
还可以帮忙处理其他问题,比如某个函数需要在 init 的 action 之后执行即可:
wpjam_load('init', function(){
// 具体代码代码
});