The Bootstrap of WordPress

1.从伪静态说起

静态网页 vs 动态网页

有些网址,如http://www.example.com/article.html,或http://www.example.com/article.txt,如果它们在服务器端的文件系统中指向真实存在的HTML文件或txt文件,那么这种网址所指向的就是“静态网页”。如果这些网址所代表的网页在服务器端文件系统中并不真实存在,而是每次都临时从数据库中读取生成,那么它们所指向的就是“动态网页”。

在未设置URL Rewrite规则的服务器中,静态网页的网址通常就像一个完整的文件系统路径,例如http://www.example.com/folder/article.html;而动态网页的网址的后面部分通常附带一连串query字符,例如http://www.example.com/folder/id=1&page=2,或http://www.example.com/?p=3等等,服务器通过parse解析这些query,进而从数据库中查询数据并呈现给客户端浏览器。

关于“伪静态”

对于动态呈示的网页,将其包含query字符串的网址rewrite为像静态网页的文件系统路径网址一样,即是通常意义上的“伪静态”。例如,将http://www.example.com/p=3重写为http://www.example.com/3/等等。

伪静态的好处有:

访问友好

对人类访问者而言,伪静态网址更加美观易读。

搜索引擎友好

相较未经rewrite的网址,伪静态网址更有利于搜索引擎优化。

伪静态的实现方式:URL Rewrite

通过http.conf

这个主要实现服务器系统级的网址重写。

通过.htaccess

这个可以实现目录级的网址重写。

通过php文件

很常见的一个例子就是,404.php页面中给出重写规则,并进而redirect至新的目标页面。

2.点击一个WordPress网址时,发生了什么

WordPress是建构于数据库之上的CMS程序,其网页主要是动态生成。当我们点击一个WordPress网站的网址时,例如http://www.wp-example.com/archive/article.html,须知这个/archive/article.html文件并不存在。WordPress比照URL Rewrite规则,从网址中提取分析出查询要求,并从数据库中提取数据,再套用theme指定的各种页面模板,将数据嵌套入模板文件,一起呈递给访问者浏览器。参阅Query Overview

WordPress .htaccess详解

WordPress默认的.htaccess文件内容是

# BEGIN WordPress
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^index.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>
# END WordPress

其中RewriteRule ^index.php$ - [L]是说,如果网址指向的是/index.php,则不必重写,直接访问(网站根下的index.php是真实存在的)。

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]

这段代码是说,如果访问的网址既不是一个真实存在的文件,也不是一个真实存在的路径(文件夹),那么就一律导向WordPress根目录下的index.php文件。详细说明可参考这里

程序流程

当网址被提交给WordPress根下的index.php后,程序主要执行以下三个方面的事情:

初始化WordPress环境

主要是初始化各种类的实例,包括wpdb类、WP_Query类、WP_Rewrite类、WP类等等。其中,wpdb类主要执行数据库SQL查询操作;WP_Query封装了几乎所有的查询逻辑;WP_Rewrite用于update .htaccess等,并且由其rewrite规则来指导网址路由解析;WP类主要执行网址路由解析、调用WP_Query::query()、设置各种全局变量等。

执行网址路由解析,通过数据库进行数据查询,将查询结果填充至相关变量,并设置各种条件标识(用于指导template的载入)

执行WordPress主函数wp()(定义于wp-includes/functions.php)。

调用网址路由解析函数WP::parse_request()从来访网址中析出数据查询条件,再通过WP::query_post()调用WP_Query::query()执行查询。

WP_Query::query()乃至整个WordPress中,get_posts()应是最重要的函数。get_posts()使用wpdb具体执行查询,再用查询结果填充WP_Query成员变量,并对条件标签进行赋值。

根据条件标识套用不同的模板文件

在模板文件中,最重要的就是The Loop

<?php /* The loop */ ?>
<?php while ( have_posts() ) : the_post(); ?>
    <?php get_template_part( 'content', get_post_format() ); ?>
<?php endwhile; ?>

其中,the_post()调用$wp_query->the_post()调用$wp_query->next_post()执行$this->post = $this->posts[$this->current_post];。可见The Loop第一次开始执行后,$wp_query->post即被赋值,从而$GLOBALS['post']即被赋予非空值。进而接下来的get_template_part( 'content', get_post_format() );调用相应的content-{slug}.php来嵌套显示post数据。

3.WP_query

引用“查询概览”

附记

permalink的生成

为什么bloginfo()之类的template tags只能在The Loop中使用?

如前所述,只有在The Loop中,$GLOBALS['post']才被赋值或才被正确赋值。