写WordPress代码时需要不停的与hooks(actions and filters)打交道,filter就像茶壶的过滤嘴,茶壶在哪它就在哪,顺序问题不那么重要。而action是一种行为,比如掀起壶盖和盖上壶盖之间就可以放一个action,在这个action里可以放茶叶,不掀起壶盖是不可以放茶叶的,所以actions加载顺序很重要。
目录
WordPress中的actions
actions可以理解为一组在系统加载到某一时刻要执行的functions集合,使用do_action()添加,例如我们经常用到的get_header()函数,是这样定义的
function get_header( $name = null ) { do_action( 'get_header', $name ); $templates = array(); if ( isset($name) ) $templates[] = "header-{$name}.php"; $templates[] = 'header.php'; // Backward compat code will be removed in a future release if ('' == locate_template($templates, true)) load_template( ABSPATH . WPINC . '/theme-compat/header.php'); }
函数第二行用do_action()注册了一个action,叫做get_header
do_action( 'get_header', $name );
如果我们在functions.php中或者插件中写
add_action('get_header','my_fun')
my_fun()这个函数就会在do_action的位置执行,而不是在functions.php运行的位置执行。
Actions加载顺序
了解WordPress中actions的执行顺序,可以知晓在这个action执行时,是否已经具备某些资源,例如登陆用户信心、例如插件API等。
要了解Actions的执行顺序,可以安装一个开发人员的插件WordPress Hook Sniffer,该插件不仅能告知actions的加载顺序,还能知道当前页面add_action操作有哪些,remove_action操作有哪些,还有filters信息。
用这个插件查看了安装默认主题时action的执行顺序,捡了一些重要的记录下来,红色字体标记了一下比较重要的阶段。
muplugins_loaded (最先加载的action)
registered_taxonomy
registered_post_type
(加载所有激活的插件的文件,这是插件代码被执行的位置)
plugins_loaded
sanitize_comment_cookies
setup_theme
(载入当前主题的functions.php,functions.php中没有用add_filter或add_action添加的函数在这里被执行)
after_setup_theme (这个钩子看着眼熟吧,默认主题开头就有)
auth_cookie_malformed
auth_cookie_valid
set_current_user (这里执行了wp_set_current_user()函数,全局变量$current_user产生)
init
widgets_init
register_sidebar
wp_register_sidebar_widget
wp_default_scripts
wp_default_styles
admin_bar_init
add_admin_bar_menus
wp_loaded
parse_request
send_headers
parse_query
pre_get_posts
posts_selection
wp
template_redirect
加载激活的主题的模板(例如index.php、page.php等)
get_header
wp_head
wp_enqueue_scripts
wp_print_styles
wp_print_scripts
wp_print_scripts
get_footer
wp_footer
从上面的列表中可以看出一些问题:
- 插件文件比主题的functions.php加载更早
- 插件加载时,wp_set_current_user()尚未执行,因此在插件文件的body中无法直接获取用户信息
- init和after_setup_theme的区别是,后者执行时尚未调用wp_set_current_user(),没有授权用户信息
- 加载主题模板文件发生在最后阶段,此阶段中不管是插件的代码还是functions.php中的代码都已执行,这样我们就不奇怪为什么在single.php中调用query_posts()会增加查询次数,query_posts()大约在pre_get_posts的位置就执行完了,等程序执行到single.php时,如果调用query_posts,只能推翻前面的结果重新查一遍。我们还能看出,避免这个问题的方法就是在functions.php中使用filters函数(posts_join, posts_groupby等)更改query_posts的查询参数,因为functions.php早于query_posts执行,方法可以参考《自定义WordPress查询的4种方法》中的第三种方法。
理解万岁
与其枯燥的去记忆什么时候该用哪个action,不如理解一下WordPress的启动过程,了解actions加载的顺序,记忆几个比较重要的过程,例如哪些actions发生在插件代码执行以后,哪些actions发生在functions.php加载以后。
3条评论
评论已关闭。