Skip to content →

WordPress的Rewrite机制分析

最近在研究WP的rewrite机制,搜到这篇不错的文章,把之前不明白的地方都一一解答了^^,放上来备用。
================================================
大家都知道,WordPress 可以通过 Apache 的 mod_rewrite 模块,使用 .htaccess 文件来重写URL,生成静态链接(或称永久链接),如 http://example.com/年/月/日/日志名/ ,使URL更加美观也对搜索引擎更友好。但具体是如何实现的,可能有些朋友不是很清楚,因此我在这里稍稍阐述下。而在不支持 .htaccess 的主机环境中,也可以使用 http://example.com/index.php/年/月/日/日志名/ 这种形式的URL,以及使用ISAPI等东东,原理都差不多,本文就不探讨了。

我以 http://www.oldjan.cn/database-dict-for-wordpress-23/2008/02/25/ 为具体例子进行分析。首先我们先来看看WordPress根目录下的 .htaccess 文件,其中有一段如下

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

意思是指,当接收到的请求不是一个文件或目录时,则会重写为WordPress根目录下的index.php文件,然后 index.php 就开始处理请求。

index.php 会包含 wp-blog-header.php, wp-blog-header.php 会包含 wp-config.php, wp-config.php 又会包含 wp-settings.php,最后 wp-settings.php 会包含一大堆文件进来,晕了吧。其中, wp-includes/query.php 中的 WP_Query 类和 wp-includes/classes.php 中的 WP 类是Rewrite最主要的,因此我们将对象实例化

$wp_the_query =& new WP_Query();
$wp_query     =& $wp_the_query;
$wp_rewrite   =& new WP_Rewrite();
$wp           =& new WP();

做了这么多准备工作后,WP真正开始处理请求了,在 wp-blog-header.php 中调用wp()函数,在这个函数执行了 WP 类的成员方法main()

function main($query_args = ”) {
    $this->init(); //初始化,获取当前用户信息
    $this->parse_request($query_args); //解析请求
    $this->send_headers(); //发送头信息
    $this->query_posts(); //查询日志
    $this->handle_404(); //操作404(URL地址不存在)
    $this->register_globals(); //注册全局变量
    do_action_ref_array(’wp’, array(&$this));
}

我们进入$this->parse_request()瞧瞧,通过$_SERVER[’REQUEST_URI’]和过滤得到字符串 ‘database-dict-for-wordpress-23/2008/02/25′ 赋值给$request_match,与存储在数据库中的rewrite规则集进行正则匹配,rewrite规则集类似与下面这个样子,当然,比下面的多了很多。

[wp-feed.php$] => index.php?feed=feed
[wp-commentsrss2.php$] => index.php?feed=rss2&withcomments=1
[(about)/trackback/?$] => index.php?pagename=$matches[1]&tb=1
[page/?([0-9]{1,})/?$] => index.php?&paged=$matches[1]
[comments/(feed|rdf|rss|rss2|atom)/?$] => index.php?&feed=$matches[1]&withcomments=1
[search/(.+)/?$] => index.php?s=$matches[1]
[category/(.+?)/?$] => index.php?category_name=$matches[1]
[tag/(.+?)/?$] => index.php?tag=$matches[1]

我的请求与 ‘([^/]+)/([0-9]{4})/([0-9]{1,2})/([0-9]{1,2})(/[0-9]+)?/?$’ 这条匹配,所以我的请求被转化为 ‘name=database-dict-for-wordpress-23&year=2008&monthnum=02& day=25&page=’,如果请求都没匹配上那就肯定404了。接着就是通过 $this->query_posts() 来查询日志信息了,查询不到那还是404,废话…

把这些都整完了,回到 wp-blog-header.php,包含 wp-includes/template-loader.php 来加载模板并显示,日志显示日志,页面显示页面,404显示404,总之就是各神归位,OVER
=====================================================
p.s.原文地址已经打不开了就不贴出来啦

Published in 笔记

4 Comments

发表评论