在了解WordPress挂载机制时,一直有一个疑惑,到底是WordPress的内核源文件先执行还是主题文件里functions.php文件先执行。为了解决这个问题,想了解WordPress的工作原理,它是如何生成网页的,各程序文件的执行顺序是什么,于是有了这篇文章。

WordPress所有的前端页面生成都要经过根目录下的index.php文件(不是主题根目录),这是通过Web服务器的rewrite规则实现的。然后通过index.php文件一步步引导WordPress环境启动,再分析请求URL返回相应数据所组成的前台页面。以下将一步步分析源码文件,以此来了解WordPress整体框架及工作原理。

第一步:加载index.php文件

该文件有效源码如下:

define('WP_USE_THEMES', true);

//定义是否加载主题文件,true为加载;

require('./wp-blog-header.php');

//加载wp-blog-header.php文件,该文件用于启动WordPress环境及模板;

第二步:加载wp-blog-header.php文件

该文件有效源码如下:

if ( !isset($wp_did_header) ) {
# 判断$wp_did_header变量是否已经设置,如果未设置则执行代码块;
$wp_did_header = true;
# 见解析1;
require_once( dirname(__FILE__) . '/wp-load.php' );
# 见解析2;
wp();
# 见解析3;
require_once( ABSPATH . WPINC . '/template-loader.php' );
# 见解析4;
}

解析1: 对$wp_did_header进行赋值,这样如果代码块已经执行过,判断就会失败,代码块就不会再执行。这种做法可以确保wp-blog-header.php文件只执行一次(重复执行的话会出现函数名冲突、变量重置等,WordPress会精神分裂的!);

解析2: 加载WP根目录下wp-load.php文件,执行初始化工作,如初始化常量、环境、加载类库和核心代码等完成WordPress环境启动工作,如加载wp-includes目录下functions.php(函数库)、class-wp.php(类库)、plugin.php(插件)、pomo目录(语言包)、query.php(数据请求)、theme.php(加载主题文件)、post-template.php(文章模板)、comment.php(评论模板)、rewrite.php(URL重写)等等。

解析3: 执行wp()函数,执行内容处理工作,如根据用户的请求调用相关函数获取和处理数据,为前端展示准备数据;

解析4: 加载根目录绝对路径下wp-includes目录中template-loader.php文件,执行主题应用工作,如根据用户的请求加载主题模板。

WordPress之所以能将用户请求的页面生成出来,都是最后这三行核心代码起的作用。

wp-load.php会完成页面生成所需要的所有环境、变量、API等,相当于做了好准备工作;wp()函数根据用户请求的URL从数据库中取出相应的数据内容备用;

template-loader.php把已经准备好的内容用主题所设定的样式展现方式给拼接出来。这三项工作完成,就可以将用户请求的页面展现出来了。

我们姑且将这三项工作也认定为三个大步骤,以下将重点分析。

第三步:加载wp-load.php文件(初始化)

该文件初始化常量(如:定义绝对路径、设定功能文件及内容文件路径等)并加载wp-config.php文件(本处不分析wp-config.php文件不存在的情况),部分核心代码如下:

define( 'ABSPATH', dirname(__FILE__) . '/' );

# 定义常量ABSPATH为根目录绝对地址;

require_once( ABSPATH . 'wp-config.php' );

# 加载根目录下wp-config.php文件;

从代码看出,本文件的主要作用就是加载wp-config.php文件,故我们可以抽象的将之看作是wp-load.php初始化时的第一个小步骤,具体如下:

1. 加载wp-config.php文件

该文件主要用于配置MySQL数据库通信信息、设定数据库表名前缀、设定密钥、设置语言及文件绝对路径等,部分核心代码如下(为省事就直接在代码后加#然后解释含义了):

define('DB_NAME', 'db_name');

# 定义数据库名db_name;

define('DB_USER', 'db_username');

# 定义数据库用户名db_username;

define('DB_PASSWORD', 'db_password');

# 定义数据库密码db_password;

define('DB_HOST', 'db_host_location');

# 定义数据库主机地址,如localhost或其他IP;

define('DB_CHARSET', 'utf8');

# 定义数据表默认文字编码,如utf8;

$table_prefix = 'wp_';

# 定义数据库表前缀,一般默认为wp_;

define('WPLANG', 'zh_CN');

# 定义WordPress语言,中文默认zh_CH,使用的汉化语言文件为/wp-content/languages目录下的zh_CH.mo文件,该文件为二进制,查看具体中文可见zh_CH.po文件;

define('WP_DEBUG', false);

# 设置开发环境DEBUG,默认为false不开启;

require_once(ABSPATH . 'wp-settings.php');

# 加载根目录下wp-settings.php文件;

代码中定义的数据库常量主要用于数据请求时通信数据库,本文件还有个主要作用就是加载了wp-settings.php文件,而该文件相当于启动WordPress环境的总指挥,下面我们就将该文件作为初始化的第二步来分析。

2. 加载wp-settings.php文件

该文件主要用于创建和定义常见变量、函数和类的库来为WordPress运行做准备,也就是说WordPress运行过程中使用的大多数变量、函数和类等核心代码都是在这个文件中定义的。这个文件相当于一个总控制器,很多常量定义、函数定义等都是在其他文件中完成,而该文件的作用就是执行那些文件或执行在那些文件中已经定义好的函数。

该文件源码分析内容较多,详见"WordPress核心文件wp-setting.php源码分析”。

第四步: 执行wp()函数(内容处理)

在这一阶段,调用wp()函数对数据库内容进行查询,并将查询的内容赋值给一些全局变量,方便在模板中使用模板标签获取相应的数据并展示在前端。该函数源码如下:

function wp( $query_vars = '' ) {
global $wp, $wp_query, $wp_the_query;
# 对变量$wp,$wp_query,$wp_the_query进行全局化;
$wp->main( $query_vars );
# 见解析1;
if ( !isset($wp_the_query) )
$wp_the_query = $wp_query;
# 见解析2;
}

解析1:调用$wp->main(),即调用对象$wp的main()方法,该对象是class-wp.php文件中WP类实例化得到的,该类主要用于启动WordPress环境,main()方法源码分析详见“WordPress核心类WP内main()方法源码分析”;

解析2:判断$wp_the_query是否设置,若未设置将其赋值为$wp_query,该对象是query.php文件中WP_Query类实例化得到的,该类作用强大,几乎WP所需要的所有数据信息都是由该类得到的,所以内容的准备工作基本都是这段代码来完成的,该类的具体分析见“”;

至此,WP根据请求准备相应数据的工作也已经完成,下面就需要加载模板并把这些数据展现到前台去了。

第五步:加载template-loader.php文件(主题应用)

该文件根据用户URL返回加载相应模板,其源码如下:

if ( defined('WP_USE_THEMES') && WP_USE_THEMES )
do_action('template_redirect');
# 如果常量WP_USE_THEMES存在且值为真,则触发挂载点(动作钩子)template_redirect;
if ( is_robots() ) :
do_action('do_robots');
return;
elseif ( is_feed() ) :
do_feed();
return;
elseif ( is_trackback() ) :
include( ABSPATH . 'wp-trackback.php' );
return;
endif;
# 判断函数is_robots(), is_feed() 和 is_trackback()的返回结果,处理 feeds 和 trackbacks,即使没有使用任何主题;
if ( defined('WP_USE_THEMES') && WP_USE_THEMES ) :
$template = false;
if ( is_404() && $template = get_404_template() ) :
elseif ( is_search() && $template = get_search_template() ) :
elseif ( is_tax() && $template = get_taxonomy_template() ) :
elseif ( is_front_page() && $template = get_front_page_template() ) :
elseif ( is_home() && $template = get_home_template() ) :
elseif ( is_attachment() && $template = get_attachment_template() ) :
remove_filter('the_content', 'prepend_attachment');
elseif ( is_single() && $template = get_single_template() ) :
elseif ( is_page() && $template = get_page_template() ) :
elseif ( is_category() && $template = get_category_template() ) :
elseif ( is_tag() && $template = get_tag_template() ) :
elseif ( is_author() && $template = get_author_template() ) :
elseif ( is_date() && $template = get_date_template() ) :
elseif ( is_archive() && $template = get_archive_template() ) :
elseif ( is_comments_popup() && $template = get_comments_popup_template() ) :
elseif ( is_paged() && $template = get_paged_template() ) :
else :
$template = get_index_template();
endif;
# 见解析1;
if ( $template = apply_filters( 'template_include', $template ) )
include( $template );
return;
endif;
# 若template_include过滤钩子上有挂载函数,则对$template进行应用,最终将内容呈现给用户;

解析1:如果常量WP_USE_THEMES存在且值为真,则判断页面类型同时给$template变量赋相应值;其中,判断页面类型的函数如is_404()位于wp-includes目录下query.php文件,该函数返回对象$wp_query中is_404()方法,若is_404()为false则继续往下判断是否是其他页面;若为true则给$template赋值为get_404_template(),该函数位于wp-includes目录下template.php文件,它返回get_query_template('404'),而该函数将页面类型传入数组$templates并应用调用函数locate_template($templates)且应用过滤器;locate_template()函数根据传入数组在主题中查找到相应的文件然后交给load_template()函数然后使用require加载,最终将用户需要的页面呈现出来;

WordPress工作原理之程序文件执行顺序的更多相关文章

  1. 【总结】/etc/rc.d/rc.local 与 /etc/profile .bash_profile .bashrc 文件执行顺序

    登陆shell与交互式非登陆shell的区别 登录shell 所谓登录shell,指的是当用户登录系统时所取的那个 shell.登录shell属于交互式shell. 登录shell将查找4个不同的启动 ...

  2. JavaScript程序的执行顺序

    JavaScript程序的执行顺序:同步==>异步==>回调 同步是阻塞模式,异步是非阻塞模式.     同步就是指一个进程在执行某个请求的时候,若该请求需要一段时间才能返回信息,那么这个 ...

  3. iOS程序的执行顺序 和 UIViewController的生命周期

    iOS程序的执行顺序 1 进入程序的入口 进入main函数, 设置AppDelegate称为函数的代理 2  程序完成加载 -[AppDelegate application:didFinishLau ...

  4. Java文件执行顺序总结

    类执行顺序 一个java文件的执行过程: 编译:加载的类,加载的时候对类中的资源进行编译,首先是静态成员变量,静态方法等,如果有相应操作,就会进行相应的操作, 并且这个Static修饰后的静态成员变量 ...

  5. wordpress工作原理

    WP初始化的过程:当你输入<yourlink>/wordpress对wordpress进行初始化时,wordpress默认会找根目录下的index.php页面,看一下index.php页面 ...

  6. 黄聪:wordpress工作原理

    WP初始化的过程:当你输入<yourlink>/wordpress对wordpress进行初始化时,wordpress默认会找根目录下的index.php页面,看一下index.php页面 ...

  7. day03_05 Python程序文件执行和与其他编程语言对比

    python在windows操作系统上是没有的,但是在linux上默认就有python 执行python程序的方式有两种: 1.交互器,缺点 程序不能永久保存,主要用于简单的语法测试 2.文件执行 对 ...

  8. Struts2工作原理和核心文件

    一.Struts2工作原理 如下图: 二.Struts2配置文件 1.web.xml 任何MVC框架都需要与Web应用整合,这就不得不借助于web.xml文件,只有配置了web.xml文件的Servl ...

  9. 关于js预编译以及js文件执行顺序的几个问题。

    关于js的执行原理,除去html页面中直接添加的代码,js代码的放置可以分为两类. //情形a           <script type="text/javascript" ...

随机推荐

  1. wpa_supplicant.conf

    转自:http://w1.fi/gitweb/gitweb.cgi?p=hostap.git;a=blob_plain;f=wpa_supplicant/wpa_supplicant.conf ### ...

  2. Mysql or Mongodb LBS快速实现方案

    http://www.wubiao.info/470 前两篇文章: 查找附近的xxx 球面距离以及Geohash方案探讨 (http://www.wubiao.info/372) 微信.陌陌 架构方案 ...

  3. python reduce()函数

    reduce()函数 reduce()函数也是Python内置的一个高阶函数.reduce()函数接收的参数和 map()类似,一个函数 f,一个list,但行为和 map()不同,reduce()传 ...

  4. 16.2.13 asp.net 学习随笔

    using System.Data.SqlClient;//连接数据库必须的 using System.Configuration; CommandType所在的命名空间 system.data; P ...

  5. CodeForces 505B Mr. Kitayuta's Colorful Graph

    Mr. Kitayuta's Colorful Graph Time Limit:1000MS     Memory Limit:262144KB     64bit IO Format:%I64d ...

  6. Hadoop_10_12虚拟机01_虚拟机NAT方式联网【自己的亲测笔记】

      NAT方式 1.查看网络信息--ifconfig(同windows中的ipconfig相同) 主要关注的是第三行内容,分别是Ip地址.广播地址.子网掩码 2.安装完系统后需要配置三个地方--IP地 ...

  7. 10686 DeathGod不知道的事情

    Description 蚂蚁是很强大的动物,除了DeathGod知道的事情外还有很多不知道的!例如… 根据某种理论,时间方向上有无数个平行世界,有的世界蚂蚁很多,有的世界蚂蚁很少,有的世界蚂蚁会繁殖, ...

  8. 枚举 POJ 2965 The Pilots Brothers' refrigerator

    题目地址:http://poj.org/problem?id=2965 /* 题意:4*4的矩形,改变任意点,把所有'+'变成'-',,每一次同行同列的都会反转,求最小步数,并打印方案 DFS:把'+ ...

  9. Log4net源码View之Logger解析

    1.简介 Logger是Log4net的三大核心载体之一,搞清楚它的意义很重大.另外两个分别是Appender和Layout.其对应关系为一个Logger对应多个Appender,一个Appender ...

  10. 【LINUX/UNIX网络编程】之使用消息队列,信号量和命名管道实现的多进程服务器(多人群聊系统)

    RT,使用消息队列,信号量和命名管道实现的多人群聊系统. 本学期Linux.unix网络编程的第三个作业. 先上实验要求: 实验三  多进程服务器 [实验目的] 1.熟练掌握进程的创建与终止方法: 2 ...