该文档假设用户熟悉Apache的mod_rewrite。如果你不了解mod_rewrite,可以先参考一下URL重写规则的入门指南,以及对重写规则层级的说明。
WP_Rewrite的作用
WP_Rewrite是WordPress中负责管理重写规则的类,你可以通过WP_Rewrite使用美观的固定链接功能。WP_Rewrite可通过若干方法充数据库的值中生成重写规则。WordPress在升级重新规则、查找日志、页面、分类索引等指定网页的URL时,都会在内部运行WP_Rewrite。WP_Rewrite作为一个单独的实例全局变量,定义于wp-includes/rewrite.php中。而$wp_rewrite在wp-settings.php中初始化。
方法和属性
这是WP_Rewrite的正式文档。不要直接获取或设置属性,可利用方法(method)与$wp_rewrite对象相互作用。
属性
$permalink_structure
数据库中的固定链接结构。这就是你在固定链接选项页面的设置,还包括 %year%, %month% 以及%post_id%等“标签”。
$category_base
插入到分类索引URL前的内容。默认为 'category/'。
$category_structure
分类索引URL结构。即$category_base 加上 '%category%'。
$author_base
插入到作者索引URL前的内容。默认为 'author/'。
$author_structure
作者索引URL结构。即$author_base 加上 '%author%'。
$feed_base
插入到feedURL前的内容。默认为 'feed/'。
$feed_structure
feed的URL结构。即$feed_base 加上 '%feed%'。
$search_base
插入到搜索URL前的内容。默认为 'search/'。
$search_structure
搜索URL结构。即$search_base 加上 '%search%'。
$comment_base
插入到$feed_structure前以获取最新评论订阅的内容。默认为 'comments'。
$comments_feed_structure
最新评论订阅的结构。即$comments_base 加上 '%feed%'。
$date_structure
基于日期的索引的URL结构。尽量为 '%年%/%月%/%日%'、'%日%/%月%/%年%' 或 '%月%/%日%/%年%,但如果没有在$permalink_structure中检测到以上结构,则默认为'%年%/%月%/%日%'。该URL结构可利用不同函数来获取特定结构:如,get_year_permastruct()函数删除$date_structure的 '%monthnum%' 标签和 '%day%' 标签。
$page_structure
页面的结构。即'%pagename%'。
$front
$permalink_structure开始标签前的任何内容。
$root
WordPress的根目录。预计为所有结构。
$matches
为重写规则的重定向部分计算返回引用时,在内部使用$matches。
$rules
重写规则。调用rewrite_rules()时设定。
$non_wp_rules
一个关于“不会重定向到WordPress的index.php文件(因此也不由WordPress进行处理)”的关联数组,该数组的粗略格式为'Pattern' => 'Substitution' (见下文)。
$rewritecode
固定链接结构可用的所有标签组成的数组。参见使用WordPress固定链接。
$rewriteplace
重写规则正则表达式部分标的标签将被什么内容替代。$rewritecode第一个元素的正则表达式将是$rewritereplace中的第一个元素,$rewritecode第二个元素的正则表达式将是$rewritereplace中的第二个元素,以此类推。
$queryreplace
重写规则重写部分的标签将被什么内容代替。代替规则同$rewritereplace。
方法(methods)
add_rewrite_tag ($tag, $pattern, $query)
利用$tag、$pattern、$query参数分别为$rewritecode、$rewritereplace与 $queryreplace 添加一个元素。如果$rewritecode中已经存在$tag,覆盖已有的值。
flush_rules()
重新生成重写规则并保存到数据库。
generate_rewrite_rule($permalink_structure, $walk_dirs = false)
从固定链接结构生成一个无装饰的重写规则。该重写规则不会为额外的页面或feed生成新规则。
generate_rewrite_rules($permalink_structure, $ep_mask = EP_NONE, $page = true, $feed = true, $forcomments = false, $walk_dirs = true)
这是一个可为已知$permalink_structure结构生成重写规则的大型函数。如果$page为true,函数生成一个新的重写规则以访问不同页面(如category/tech/page/2指向'tech'分类索引的第二页)。若$feed为true,函数又生成一个重写规则以获取当前页面的feed信息,若$forcomments为true,则函数获取的是评论feed。如果$walk_dirs为true,则函数为用户提供的固定链接结构的所有目录各生成一个新的重写规则,例如,如果你提供一个'/%year%/%month%/%day/'结构,则函数分别为 '/%year%/', /%year%/%month%/' 与'/%year%/%month%/%day%/'各生成一个重写规则。返回的关联数组以重写规则的正则表达式部分为关键字,重写规则的重定向部分为值。
get_date_permastruct(), get_category_permastruct(), get_date_permastruct() 等
如果没有设置相应的属性,将属性移入(如将$date_structure属性移入 get_date_permastruct())并返回属性。get_month_permastruct() 函数与 get_year_permastruct()函数没有相应的属性:这两个函数接收$date_structure,删除那些比他们的要求更详细的标签(例如,get_month_permastruct() 会删除'%day%' 标签,因为它只需要年月信息)。
init()
设置对象,从数据库中设定$permalink_structure 与 $category_base。将$root设为 $index 加上 '/'。将$front设为固定链接结构第一个标签前的所有内容。复原其它所有属性。
mod_rewrite_rules()
返回所有规则的字符串(而非数组)。这些规则包裹在一个Apache的 <IfModule>块中,以确保启用mod_rewrite。
page_rewrite_rules()
返回你创建的所有页面的所有重写规则
rewrite_rules()
与在generate_rewrite_rules()中一样,移入并返回带有关联数组的$rules变量。rewrite_rules()在日志、日期、评论、搜索、分类、作者以及页面链接结构中生成。
set_category_base($category_base)
更改分类基础。
set_permalink_structure($permalink_structure)
更改固定链接结构
using_index_permalinks()
如果你的博客使用PATHINFO链接,返回true。
using_mod_rewrite_permalinks
如果你的博客通过mod_rewrite使用美观的固定链接结构,返回true
using_permalinks()
如果你的博客使用热河固定链接结构(如非默认的查询URI ?p=n, ?cat=n),返回true
WP_Rewrite (构造器)
调用init()
wp_rewrite_rules()
与rewrite_rules()一样,返回重写规则数组,不同之处在于,wp_rewrite_rules()使用的是$matches[xxx](其中xxx表示数字),而不是使用mod_rewrite逆向引用$xxx(其中xxx表示数字)。当你打算在PHP中使用重写规则而非将重写规则写入.htaccess文件时,wp_rewrite_rules()会是一个非常有用的工具。
插件钩子(hook)
重写规则是博客功能的重要部分。WordPress允许插件在多个时刻链接到WordPress进程。尤其是rewrite_rules()中包括了九个过滤器和一个钩子,可以准确控制重写规则进程。下面是你可以在rewrite_rules()中过滤的内容:
- 要过滤为固定链接URL而生成的重写规则,请用post_rewrite_rules
- 要过滤为基于日期的索引/存档URL而生成的重写规则,请用date_rewrite_rules
- 要过滤为分类存档URL而生成的重写规则,请用category_rewrite_rules
- 要过滤为搜索URL而生成的重写规则,请用search_rewrite_rules
- 要过滤为最新评论feed URL而生成的重写规则,请用comments_rewrite_rules
- 要过滤为作者索引URL而生成的重写规则,请用author_rewrite_rules
- 要过滤为页面而生成的重写规则,请用page_rewrite_rules
- 要过滤为博客根目录而生成的重写规则,请用root_rewrite_rules
- 要过滤所有重写规则,请用rewrite_rules_array
- 动作钩子generate_rewrite_rules在所有已创建规则之后运行。如果你的函数使用参数,generate_rewrite_rules会将一个引用传递给整个 $wp_rewrite对象。
mod_rewrite_rules()函数接收rewrite_rules()生成的数组,并将数组转换为一系列重写规则以供.htaccess文件使用。mod_rewrite_rules()函数也有一个过滤器mod_rewrite_rules,该过滤器将所有规则组成的字符串传递给.htaccess,包括 <IfModule> 周边版块。(注意:还有些插件使用rewrite_rules钩子,但WordPress现在已经不支持这一功能)。
示例
(参见自定义查询语句)插件能对$wp_rewrite对象做出的最明显操作,就是添加重写规则。用插件添加重写规则是件非常简单的事,只需要过滤通用的 rewrite_rules_array。
下面是一个将http://mysite/project/1改写为 http://mysite/index.php?pagename=project&id=1的例子:
add_filter('rewrite_rules_array','wp_insertMyRewriteRules');
add_filter('query_vars','wp_insertMyRewriteQueryVars');
add_filter('init','flushRules');
// Remember to flush_rules() when adding rules
function flushRules(){
global $wp_rewrite;
$wp_rewrite->flush_rules();
}
// Adding a new rule
function wp_insertMyRewriteRules($rules)
{
$newrules = array();
$newrules['(project)/(d*)$'] = 'index.php?pagename=$matches[1]&id=$matches[2]';
return $newrules + $rules;
}
// Adding the id var so that WP recognizes it
function wp_insertMyRewriteQueryVars($vars)
{
array_push($vars, 'id');
return $vars;
}
Jerome开发的 Keywords插件利用以上方法激活类似http://example.com/tag/sausages的URL。
function keywords_createRewriteRules($rewrite) {
global $wp_rewrite;
// add rewrite tokens
$keytag_token = '%tag%';
$wp_rewrite->add_rewrite_tag($keytag_token, '(.+)', 'tag=');
$keywords_structure = $wp_rewrite->root . "tag/$keytag_token";
$keywords_rewrite = $wp_rewrite->generate_rewrite_rules($keywords_structure);
return ( $rewrite + $keywords_rewrite );
}
相较于将重写规则插入到$rewrite数组,Jerome选择用WP_Rewrite函数generate_rewrite_rules()生成另一个数组——$keywords_rewrite。使用该函数意味着插件不必为附加页面(如page/2)与附加feed(如feed/atom)生成新的重写规则。Jerome新生成的数组会被添加到$rewrite数组并返回。
下面这个例子更加简单,来自Ryan Boren的Feed Director插件。该插件将类似于 http://example.com/feed.xml这样的URL重定向到类似于http://example.com/feed/rss2的URL:
function feed_dir_rewrite($wp_rewrite) {
$feed_rules = array(
'index.rdf' => 'index.php?feed=rdf',
'index.xml' => 'index.php?feed=rss2',
'(.+).xml' => 'index.php?feed=' . $wp_rewrite->preg_index(1)
);
$wp_rewrite->rules = $feed_rules + $wp_rewrite->rules;
}
// Hook in.
add_filter('generate_rewrite_rules', 'feed_dir_rewrite');
这里的数组非常简单,因此完全没有必要调用generate_rewrite_rules()。插件的规则会被添加到WordPress的规则中。注意,这里的函数过滤了 generate_rewrite_rules,将引用作为参数(而非重写规则),接收到整个$wp_rewrite对象中。
当然,由于你是在WordPress还没有处理重写规则前将重写规则添加到数组中,当WordPress开始对重写规则进行操作时(如将重写规则写入.htaccess文件),会将你的插件的重写规则也包括在内。
非WordPress重写规则
<?php
$wp_rewrite->non_wp_rules = array( 'Pattern' => 'Substitution' );
print_r($wp_rewrite->mod_rewrite_rules());
?>
输出
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /wp_home/
RewriteRule ^Pattern /wp_home/Substitution [QSA,L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /wp_home/index.php [L]
</IfModule>
其中/wp_home/是WordPress的根目录(若WordPress安装在网络根目录下,则WordPress根目录为根URL/。)
分类:中文手册