首页 > Web开发, 动态语言, 挨踢(IT) > WordPress源码分析(二):连接信息的提交与配置文件的生成

WordPress源码分析(二):连接信息的提交与配置文件的生成

2013年2月2日 发表评论 阅读评论 1,684 人阅读    

WordPress源码分析系列

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

  在上一篇文章“WordPress源码分析(一):安装过程中页面的加载顺序”中,D瓜哥分析到Wordpres通过wp/wp-admin/setup-config.php页面获取、处理数据库连接配置信息。今天,D瓜哥接着从这里开始,对wp/wp-admin/setup-config.php文件的源代码进行“庖丁解牛”!

“潜规则”

  由于wp/wp-admin/setup-config.php文件真的很大,有287行之多。所以,D瓜哥在讲解的时候,只展示和详解部分相关的内容。

  另外,为了方便大家阅读,D瓜哥会把所展示的代码行号调整成和源文件保持一致

创建配置文件的提示

  打开wp/wp-admin/setup-config.php文件,从上往下看。各种define和require,这些都先略过。wp_check_php_mysql_versions()函数我们已经讲过,检查PHP和MySQL的版本,不符合要求则报错;wp_load_translations_early()是加载本地化文件。第65到76行判断wp-config.php、wp-config-sample.php以及wp-settings.php文件是否存在,不存在则报错!请注意第78行:

$step = isset( $_GET['step'] ) ? (int) $_GET['step'] : 0;

  对PHP略为了解的人都知道,这浏览器提交的参数中取名称为step的参数,如果没有则取0。请大家记住变量$step,她将会是分析一下流程中的重要路标!请先看一下浏览器中的路径,是不是http://127.0.0.1/wp/wp-admin/setup-config.php,则现在变量$step的值是0。记住这个值,然后往下看,看到的第一个使用这个变量的代码段是一个switch块,具体代码如下:

switch($step) {
	case 0:
		display_header();
?>

<p><?php _e( 'Welcome to WordPress. Before getting started, we need some information on the database. You will need to know the following items before proceeding.' ) ?></p>
<ol>
	<li><?php _e( 'Database name' ); ?></li>
	<li><?php _e( 'Database username' ); ?></li>
	<li><?php _e( 'Database password' ); ?></li>
	<li><?php _e( 'Database host' ); ?></li>
	<li><?php _e( 'Table prefix (if you want to run more than one WordPress in a single database)' ); ?></li>
</ol>
<p><strong><?php _e( "If for any reason this automatic file creation doesn't work, don't worry. All this does is fill in the database information to a configuration file. You may also simply open <code>wp-config-sample.php</code> in a text editor, fill in your information, and save it as <code>wp-config.php</code>." ); ?></strong></p>
<p><?php _e( "In all likelihood, these items were supplied to you by your Web Host. If you do not have this information, then you will need to contact them before you can continue. If you&#8217;re all ready&hellip;" ); ?></p>

<p class="step"><a href="setup-config.php?step=1<?php if ( isset( $_GET['noapi'] ) ) echo '&amp;noapi'; ?>" class="button"><?php _e( 'Let&#8217;s go!' ); ?></a></p>
<?php
	break;
?>

  现在页面上显示的内容,正是这段代码的执行的结果。大家可以看一下switch代码块包含的代码,直到这个文件的倒数第三行,几乎包含了整个文件。再结上一篇文章中,跳来跳去的链接变化可以看出,Wordpress对数据库配置信息的设置正是在这个文件来处理的!

  请大家注意一下第122行,下一步就是要展示数据库连接信息的表单,而且第122行正是用于跳转的a标签。下面,给大家分析一下数据库连接信息的表单展示。

数据库连接信息的表单展示

  点击一下页面的“现在就开始!”按钮,跳转到了数据库连接信息的表单展示页面。注意一下浏览器地址栏里的网址,已经变成http://127.0.0.1/wp/wp-admin/setup-config.php?step=1,则现在的变量$step的值为1,根据上文分析的结果,现在显示case为1的代码了。代码有点多,D瓜哥只展示重点代码:

	case 1:
		display_header();
	?>
<form method="post" action="setup-config.php?step=2">

  从form标签的action属性值来看,这个表单处理的页面时setup-config.php?step=2。从这里的step值来看,,表单数据的接收由switch代码块中,case为2的片段来处理。下面,我们来说一下表单数据的接收。

表单信息的接收

  先创建好数据库,配置好数据库用户和密码,然后将数据库连接信息填到表单的相应文本框中,点击“提交”,下面,我们先说配置正确情况下的处理。最后,再说出错时,会有什么情况。先看看表单数据的接收。代码片段如下:

	case 2:
	foreach ( array( 'dbname', 'uname', 'pwd', 'dbhost', 'prefix' ) as $key )
		$$key = trim( stripslashes( $_POST[ $key ] ) );

  请大家注意这段代码:首先定义了一个数组,并初始化;然后,将数组中的数组元素作为HTTP请求的变量名从$_POST取得从浏览器提交过来的参数值;再然后,将这些参数值赋值给以这个数组中的数组元素作为变量名的可变变量。以后,即使增加变量值,只需要在数组中增加一项即可!简练又不是灵活,非常精巧!

  这里获取的到的参数值,会定义到一组常量中去。代码如下:

	define('DB_NAME', $dbname);
	define('DB_USER', $uname);
	define('DB_PASSWORD', $pwd);
	define('DB_HOST', $dbhost);

  定义成常量有两个用途:一、用于检查数据库连接信息的正确性;二、可以生成配置文件。在讲解配置文件的生成时,就会用到这部分信息。。

  下面,我们讲解一下这个配置文件的生成。

配置文件的生成

  在我们开始讲解这一节内容时,我们先读取配置文件的“样板文件”,以备后用!代码如下:

$config_file = file(ABSPATH . 'wp-config-sample.php');

  打开可以打开这个样板文件看一下,只需要将刚刚的表单信息填充到相应的数据项中就是一个完整的配置文件。下面,我们看一个这个“填充”的过程。

	foreach ( $config_file as $line_num => $line ) {
		if ( '$table_prefix  =' == substr( $line, 0, 16 ) ) {
			$config_file[ $line_num ] = '$table_prefix  = \'' . addcslashes( $prefix, "\\'" ) . "';\r\n";
			continue;
		} // 从224到这行,用于定义数据库表的前缀。

		if ( ! preg_match( '/^define\(\'([A-Z_]+)\',([ ]+)/', $line, $match ) )
			continue;

		$constant = $match[1];
		$padding  = $match[2];

		switch ( $constant ) {
			case 'DB_NAME'     :
			case 'DB_USER'     :
			case 'DB_PASSWORD' :
			case 'DB_HOST'     :
				$config_file[ $line_num ] = "define('" . $constant . "'," . $padding . "'" . addcslashes( constant( $constant ), "\\'" ) . "');\r\n";
				break;
			case 'AUTH_KEY'         :
			case 'SECURE_AUTH_KEY'  :
			case 'LOGGED_IN_KEY'    :
			case 'NONCE_KEY'        :
			case 'AUTH_SALT'        :
			case 'SECURE_AUTH_SALT' :
			case 'LOGGED_IN_SALT'   :
			case 'NONCE_SALT'       :
				$config_file[ $line_num ] = "define('" . $constant . "'," . $padding . "'" . $secret_keys[$key++] . "');\r\n";
				break;
		}
	}
	unset( $line );

  第229行中,判断“样本文件”是否以define()开头,如果是,将匹配的项放入到变量$match中。紧接着,在232、233行中,把匹配的第一项赋值给$constant,大家可以打开“样本文件”看一下,你会发现,匹配出来的一些变量和上面定义的数据库连接信息的常量名是一样的。由此可见,这个变量就是指代一个“常量名”。

  第236到240行,使用switch语句,巧妙地把“样板文件”中,有关数据库连接信息的配置行替换成实际的连接信息。注意constant( $constant ),结合“样本文件”中匹配出来的常量名,和刚刚定义的常量名,这不正说明上面定义常量的用途嘛!

  第242到250行,牵涉到一个很重要的问题:安全问题!这个是一个很重要的议题。我们以后专门来讲!

  到这个循环运行结束,刚刚提交的所有数据库连接信息都已经配置到了数组$config_file中,下面只需要把这个变量写入到配置文件中即可!写入的过程如下:

		$handle = fopen(ABSPATH . 'wp-config.php', 'w');
		foreach( $config_file as $line ) {
			fwrite($handle, $line);
		}
		fclose($handle);
		chmod(ABSPATH . 'wp-config.php', 0666);

  到这里,配置文件的生成就大功告成了!下面,我们简单讲解一下,这个过程中的错误提示以及处理。

配置信息的错误处理

  D瓜哥感兴趣的是出错后,再重新返回到配置信息填写页面时,如何保持原来的填写记录。所以,D瓜哥今天只给大家介绍一种情况:数据库表前缀填写错误的处理。具体代码如下:

	$tryagain_link = '</p><p class="step"><a href="setup-config.php?step=1" onclick="javascript:history.go(-1);return false;" class="button">' . __( 'Try Again' ) . '</a>';

	if ( empty( $prefix ) )
		wp_die( __( '<strong>ERROR</strong>: "Table Prefix" must not be empty.' . $tryagain_link ) );

	// Validate $prefix: it can only contain letters, numbers and underscores.
	if ( preg_match( '|[^a-z0-9_]|i', $prefix ) )
		wp_die( __( '<strong>ERROR</strong>: "Table Prefix" can only contain numbers, letters, and underscores.' . $tryagain_link ) );

  从代码中可以看出,表前缀只能是大小写字母或下划线;并且不能为空。出错后,由第168行中的a标签处理。注意a标签中的onclick属性,从代码上来看直接使用JavaScript返回到上一个页面,然后返回false,等于阻止了a标签的默认事件!没想到错误处理竟然这样解决!代码简单,功能完备!赞!

  继续关注168行中的a标签,大家注意到了,这里的href属性也有值。上面都已经阻止默认事件了,这里的值还有用吗?这里给大家留一个悬念。以后D瓜哥会专门出一个系列来讲解这个问题。

  通过这两篇文章,已经解决了D瓜哥在第一篇文章中提到的问题:如何接收配置信息,生成配置文件?但是,现在又有了一个新问题:数据库模型是如何建立起来的?这个问题,D瓜哥留到下一篇文章来讲解。敬请期待!



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

  1. 2013年3月5日14:31 | #1

    呵呵,地瓜哥过年好啊……
    怎么1个多月没有写博客了?
    不会是要放弃了吧?

    • D瓜哥
      2013年3月6日14:19 | #2

      不会放弃的!写了,由于还没整理好,所以一直迟迟没有发表。不过,今天发表了一篇。欢迎来看看。哈哈

  2. winsley
    2013年4月7日10:50 | #3

    地瓜哥,期待后续的相关文章。

    • D瓜哥
      2013年4月7日11:45 | #4

      肯定有的!只不过,现在有一些思路还没时间写出来!等有时间再说吧。哈哈

  3. 2015年4月28日22:15 | #5

    分析的真不错!赞一个!

  4. ivan
    2016年2月19日11:20 | #6

    分析的真不错!赞一个!

  1. 本文目前尚无任何 trackbacks 和 pingbacks.