首页 > Web开发, 动态语言, 挨踢(IT) > WordPress源码分析(一):安装过程中页面的加载顺序

WordPress源码分析(一):安装过程中页面的加载顺序

2013年1月29日 发表评论 阅读评论 4,750 人阅读    

  WordPress 是一个功能非常强大的博客系统,插件众多,易于扩充功能。安装和使用都非常方便。 WordPress 已经成为主流的 Blog 搭建平台。吹嘘到此为止。(●⌒◡⌒●)所以,D瓜哥也是使用的Wordpress搭建我的博客:“地瓜哥”博客网

  前两天,一个非常要好的朋友让帮忙做个网站,以前没整过这种东西。头一次整,觉得挺头大的!首先,第一个问题就是网站的安装过程怎么处理?配置文件如何生成?可是,这两个问题该如何解决呢?

  D瓜哥首先想到的就是Wordpress的安装过程:过程简单,配置清晰,只需配置一下数据库连接信息和博客的基本信息,Wordpress立马就能跑起来。非常好的“山寨”对象。整好可以借此机会,研究一下Wordpress的源代码,既可以学习一下PHP,又能深入了解一下Wordpress的实现细节,方便以后定制;还能解决我的问题。真是一箭三雕,何乐而不为?

程序下载

  Wordpress是由PHP开发的,而且是开源的,所以,只要把Wordpress的压缩包下载下来,解压后就是Wordpress的源代码,非常方便。Wordpress目前最新版是 3.5.1。D瓜哥认为“大版本”刚刚推出来,肯定还有不少的Bug。所以,为了稳定起见,还是3.4.2版比较靠谱。所以,下面的分析师针对3.4.2版的。另外,Wordpress的下载页面是:WordPress下载页面

安装过程中页面的加载顺序

  下载Wordpress 3.4.2版,将下载的压缩包,解压到本机的Web服务器的相应目录下,将文件夹名称修改为wp。先声明一下,在下文中,D瓜哥假设Wordpress的根目录是wp。打开wp文件夹,里面躺着一堆PHP文件和三个文件夹,犹如很多性感多姿的美女,是不是已经“蠢蠢欲动”?

  老虎吃天无处下爪!这么多美女,我们该从哪个开始下手呢?!也许我们能从Wordpress的安装过程看出一些端倪。启动Web服务器,我们打开http://127.0.0.1/wp/,请观察浏览器地址栏中的地址,你是不是惊讶为啥没有指定文件名,但是浏览器缺正常显示了?但是显示的是哪个文件内容呢?

  这里就要先了解一下Apache服务器的配置:DirectoryIndex。DirectoryIndex指令用于设置当客户端在请求的目录名的末尾刻意添加一个”/”以表示请求该目录的索引时,服务器需要寻找的资源列表。也就是说,当用户访问某个文件夹下时,服务器会默认加载哪个文件来显示。在D瓜哥个人电脑上使用的XAMPP集成环境中,配置如下:

#
# DirectoryIndex: sets the file that Apache will serve if a directory is requested.
#
<IfModule dir_module>
    DirectoryIndex index.php index.pl index.cgi index.asp index.shtml index.html index.htm \
                   default.php default.pl default.cgi default.asp default.shtml default.html default.htm \
                   home.php home.pl home.cgi home.asp home.shtml home.html home.htm
</IfModule>

  那这个列表和我们的Wordpress文件列表相比对,大家也许马上就确认wp/index.php文件会首先加载。另外,我们也可以打开http://127.0.0.1/wp/index.php来验证一下,你有木有发现和前一个连接显示的内容是一样的?!。使用文本编辑器打开wp/index.php文件,内如如下:

<?php
/**
 * Front to the WordPress application. This file doesn't do anything, but loads
 * wp-blog-header.php which does and tells WordPress to load the theme.
 *
 * @package WordPress
 */

/**
 * Tells WordPress to load the WordPress theme and output it.
 *
 * @var bool
 */
define('WP_USE_THEMES', true);

/** Loads the WordPress Environment and Template */
require('./wp-blog-header.php');

  从这个文件开始的注释中可以看出,这个文件只是用来加载wp/wp-blog-header.php文件的。我们就顺藤摸瓜,打开这个文件去看个究竟。

<?php
/**
 * Loads the WordPress environment and template.
 *
 * @package WordPress
 */

if ( !isset($wp_did_header) ) {

	$wp_did_header = true;

	require_once( dirname(__FILE__) . '/wp-load.php' );

	wp();

	require_once( ABSPATH . WPINC . '/template-loader.php' );

}

  这个文件还是没有什么内容,不过这个文件的作用在注释中说的很清楚:加载Wordpress配置信息和模板。目前,我们暂时把注意力集中在第十二行上,也前一个文件一样,是require_once函数,即把文件引入进来。下面,我们接着看看这个文件wp/wp-load.php:

<?php
/**
 * Bootstrap file for setting the ABSPATH constant
 * and loading the wp-config.php file. The wp-config.php
 * file will then load the wp-settings.php file, which
 * will then set up the WordPress environment.
 *
 * If the wp-config.php file is not found then an error
 * will be displayed asking the visitor to set up the
 * wp-config.php file.
 *
 * Will also search for wp-config.php in WordPress' parent
 * directory to allow the WordPress directory to remain
 * untouched.
 *
 * @internal This file must be parsable by PHP4.
 *
 * @package WordPress
 */

/** Define ABSPATH as this file's directory */
define( 'ABSPATH', dirname(__FILE__) . '/' );

error_reporting( E_CORE_ERROR | E_CORE_WARNING | E_COMPILE_ERROR | E_ERROR | E_WARNING | E_PARSE | E_USER_ERROR | E_USER_WARNING | E_RECOVERABLE_ERROR );

if ( file_exists( ABSPATH . 'wp-config.php') ) {

	/** The config file resides in ABSPATH */
	require_once( ABSPATH . 'wp-config.php' );

} elseif ( file_exists( dirname(ABSPATH) . '/wp-config.php' ) && ! file_exists( dirname(ABSPATH) . '/wp-settings.php' ) ) {

	/** The config file resides one level above ABSPATH but is not part of another install */
	require_once( dirname(ABSPATH) . '/wp-config.php' );

} else {

	// A config file doesn't exist

	// Set a path for the link to the installer
	if ( strpos($_SERVER['PHP_SELF'], 'wp-admin') !== false )
		$path = 'setup-config.php';
	else
		$path = 'wp-admin/setup-config.php';

	define( 'WPINC', 'wp-includes' );
	define( 'WP_CONTENT_DIR', ABSPATH . 'wp-content' );
	require_once( ABSPATH . WPINC . '/load.php' );
	require_once( ABSPATH . WPINC . '/version.php' );

	wp_check_php_mysql_versions();
	wp_load_translations_early();

	require_once( ABSPATH . WPINC . '/functions.php' );

	// Die with an error message
	$die  = __( "There doesn't seem to be a <code>wp-config.php</code> file. I need this before we can get started." ) . '</p>';
	$die .= '<p>' . __( "Need more help? <a href='http://codex.wordpress.org/Editing_wp-config.php'>We got it</a>." ) . '</p>';
	$die .= '<p>' . __( "You can create a <code>wp-config.php</code> file through a web interface, but this doesn't work for all server setups. The safest way is to manually create the file." ) . '</p>';
	$die .= '<p><a href="' . $path . '" class="button">' . __( "Create a Configuration File" ) . '</a>';

	wp_die( $die, __( 'WordPress &rsaquo; Error' ) );
}

  直接看高亮部分的代码,第26行是判断是否有wp/wp-config.php文件;第31行是在wp/wp-config.php文件存在的情况下,判断wp/wp-settings.php是不是不存在。我们可以查看我们刚刚解压开的代码,没有wp/wp-config.php文件,则执行第38到62行的内容,你仔细看一下代码,有木有发现很熟悉,是不是页面上的内容(或者相关翻译)?

  这时,请查看一下浏览器中的地址,是不是http://127.0.0.1/wp/index.php或者http://127.0.0.1/wp/?从这里可以看出,使用require_once函数,可以将另外一个文件的内容直接导入到本文件中。这是服务端发生的,对于客户端来说是透明的。

  继续关注浏览器的网址!现在,点击页面的“创建配置文件”按钮,再次查看浏览器中网址,是不是变成了http://127.0.0.1/wp/wp-admin/setup-config.php?怎么跳转了呢?下面我们截取一些

	// A config file doesn't exist

	// Set a path for the link to the installer
	if ( strpos($_SERVER['PHP_SELF'], 'wp-admin') !== false )
		$path = 'setup-config.php';
	else
		$path = 'wp-admin/setup-config.php';

	define( 'WPINC', 'wp-includes' );
	define( 'WP_CONTENT_DIR', ABSPATH . 'wp-content' );
	require_once( ABSPATH . WPINC . '/load.php' );
	require_once( ABSPATH . WPINC . '/version.php' );

	wp_check_php_mysql_versions();
	wp_load_translations_early();

	require_once( ABSPATH . WPINC . '/functions.php' );

	// Die with an error message
	$die  = __( "There doesn't seem to be a <code>wp-config.php</code> file. I need this before we can get started." ) . '</p>';
	$die .= '<p>' . __( "Need more help? <a href='http://codex.wordpress.org/Editing_wp-config.php'>We got it</a>." ) . '</p>';
	$die .= '<p>' . __( "You can create a <code>wp-config.php</code> file through a web interface, but this doesn't work for all server setups. The safest way is to manually create the file." ) . '</p>';
	$die .= '<p><a href="' . $path . '" class="button">' . __( "Create a Configuration File" ) . '</a>';

	wp_die( $die, __( 'WordPress &rsaquo; Error' ) );

  从上往下往下看代码,我们首先会注意到,文件还导入了wp/wp-includes/load.php和wp/wp-includes/version.php两个文件。在wp/wp-includes/load.php中,定义了一下函数,比如下面紧接着执行的两个函数,wp_check_php_mysql_versions()检查PHP环境和MySQL的版本和可用性;而wp_load_translations_early()则是加载本地化文件。在wp/wp-includes/version.php文件中只是则是定义了一些常量。这不是我们的主线,不过多介绍!

  再往下看,发现有一个<a>标签。另外我们从浏览器中可以看出浏览器做了一次跳转,而且跳转的页面是wp/wp-admin/setup-config.php。现在我们让我们暂时把代码,放一边,点击一下页面上的“现在就开始!”按钮,再次查看一下页面的链接,是不是变成了http://127.0.0.1/wp/wp-admin/setup-config.php?step=1?页面是不是显示要配置数据库连接信息的表单?不用管,这些配置信息是否正确,直接点击“提交”按钮。注意浏览器的地址栏,网址是不是变成了http://127.0.0.1/wp/wp-admin/setup-config.php?step=2?啊,页面报错了!没事,点击一下“重试”按钮,重新开始。页面有跳转到了:http://127.0.0.1/wp/wp-admin/setup-config.php?step=1……

  从上面的来回跳转,D瓜哥猜测配置信息的处理就在wp/wp-admin/setup-config.php来完成的。所以,下一篇D瓜哥集中精力来分析配置信息的提交和配置文件的生成。

一些问题

  在这个分析过程中还发现了一些问题,希望熟悉PHP的朋友能帮忙解答一下。问题列表如下:

  1. index.php等文件中,没用使用和<?php配对的?>结尾。这是为什么?
  2. 在一个文件中定义了常量,必须导入到其他文件中才能再次使用吗?

参考资料

  1. 维基百科中对Wordpress的介绍
  2. Apache 2.2中文参考手册


作 者: D瓜哥,https://www.diguage.com/
原文链接:https://wordpress.diguage.com/archives/98.html
版权声明:非特殊声明均为本站原创作品,转载时请注明作者和原文链接。

  1. 2013年4月9日12:46 | #1

    index.php等文件中,没用使用和结尾。这是为什么?
    在php,如果整个.php文件内容都是php代码,可以忽略掉?>结尾标签。
    在一个文件中定义了常量,必须导入到其他文件中才能再次使用吗?
    是的。文件与文件直接并没有直接的关联,只有require和include引入之后,才会发生关系。

  2. thinksdiff.com
    2014年3月17日10:12 | #2

    楼主说得不错啊 厉害

  3. 2015年4月28日16:26 | #3

    发现了个错误,第31行不是在判断“wp/wp-config.php文件存在的情况下,判断wp/wp-settings.php是不是不存在”。dirname()函数如果参数是文件的话,结果就是该文件的绝对路径,如果参数是目录的话给出的是该目录的上一级目录。那么dirname(ABSPATH)应该是wp的上一级目录。这应该是一种安全机制吧,wp-config.php包含了数据库的信息,如果直接放在网站根目录下会有安全隐患,因此可以放到网站根目录的上一级目录。我试过,将wp-config.php移到上一级目录网站可以照常访问。

  4. Assignment Expert
    2019年1月16日18:42 | #4

    如果整个.php文件内容都是php代码,可以忽略掉?>结尾标签。
    在一个文件中定义了常量,必须导入到其他文件中才能再次使用吗?
    是的。文件与文件直接并没有直接的关联,只有require和include引入之后,才会发生关

  1. 2013年2月2日00:05 | #1