假期无事,又重新将自己的网站(第6小站)上线,放弃了原来的dokuwiki(优点:部署简单,无需数据库支持,ui简洁;缺点:文章管理逻辑奇特,需要手写markdown),然后自豪的采用wordpress,搞定主题,一阵改头换面之后,发现了一些美中不足的东西———丑陋的url,贴几个大家感受下:
sixther.me/?p=85 #特定文章的url,根据post_id查询
sixther.me/?m=201512 #查看特定日期的文章,根据date string查询
sixther.me/?category=15 #查看特定类别的文章,根据catetory_id查询
sixther.me/?tag=monitor #查看特定标签的文章,根据tag_string查询
sixther.me/?author=1 #查看特定作者的文章,根据author_id查询
注:这些写法都省略了index.php,完整的写法应为:
https://sixther.me/index.php?author=1
url也属于UI的一部分,也应该做到简洁友好,至少也得让网络爬虫认识,第一步,先使用wordpress自带的固定链接设置将其静态化,这样设置完之后,上面的url变成了如下样子:
固定链接:https://sixther.me/%postname%.html
sixther.me/vim-template-for-python-file.html
sixther.me/2015/12
sixther.me/category/linux
sixther.me/tag/python
sixther.me/author/sixther
对,这应该是合理的,也应该是最终的目标,但这时候出现大问题了,所有的链接,包括文章,分类,日期,标签,作者都变成了404页面,不知道这一点算不算是wordpress的bug,固定链接的功能不应该就是这样的么,也或许跟版本有关系,第6小站用的是4.4的版本,也就是说,目前的网站不认识这些优雅的url,只认识上面那些丑陋的url,这种情况可以通过nginx来解决,细思一下,也不能完全解决,因为优雅的url里面都是name属性的东西,丑陋的url里都是id属性的东西,只有tag跟date可以用rewrite搞定,先加上再说:
rewrite ^/([0-9]+)/([0-9]+) /index.php?m=$1$2 last;
rewrite ^/tag/(.*) /index.php?tag=$1 last;
bingo!!
再来考虑剩下的几个,显然,解决办法有两个,一是找到index.php通过name查询结果的参数,另一个是让程序生成href的时候用id来生成,那只能去看wordpress代码了,最开始注意到了auth-template.php的文件里面有个get_author_posts_url函数:
function get_author_posts_url($author_id, $author_nicename = '') {
global $wp_rewrite;
$auth_ID = (int) $author_id;
$link = $wp_rewrite->get_author_permastruct();
if ( empty($link) ) {
$file = home_url( '/' );
$link = $file . '?author=' . $auth_ID;
} else {
if ( '' == $author_nicename ) {
$user = get_userdata($author_id);
if ( !empty($user->user_nicename) )
$author_nicename = $user->user_nicename;
}
$link = str_replace('%author%', $author_nicename, $link);
//$link = str_replace('%author%', $author_id, $link);
$link = home_url( user_trailingslashit( $link ) );
}
$link = apply_filters( 'author_link', $link, $author_id, $author_nicename );
return $link;
}
注释那一行是我本来打算改的,后来事实证明这样可以将按照author id查询改好,可以看到,生成author_posts_url的方法就是将%author%替换为$author_nicename,有点mvc基础的同学都会明白%author%就是模版变量,那category,post应该也是这样做的吧,用"%category% && str_replace"的关键字搜索category-template.php文件,却并没有类似代码,真是搞不懂wordpress的代码逻辑,有机会一定得梳理下,第二种办法就追到这里没再下去了。
然后就是各种google了,基本关键字就是“wordpress api,wordpress category 404...”之类的,然后就发现了query.php的文件,打开文件的第一行就让我看到了解决问题的希望(是一行注释):
/**
* WordPress Query API
*
* The query API attempts to get which part of WordPress the user is on. It
* also provides functionality for getting URL query information.
*
再往下看,犹如发现新大陆:
public function fill_query_vars($array) {
$keys = array(
'error'
, 'm'
, 'p'
, 'post_parent'
, 'subpost'
, 'subpost_id'
, 'attachment'
, 'attachment_id'
, 'name'
, 'static'
, 'pagename'
, 'page_id'
, 'second'
, 'minute'
, 'hour'
, 'day'
, 'monthnum'
, 'year'
, 'w'
, 'category_name'
, 'tag'
, 'cat'
, 'tag_id'
, 'author'
, 'author_name'
, 'feed'
, 'tb'
, 'paged'
, 'comments_popup'
, 'meta_key'
, 'meta_value'
, 'preview'
, 's'
, 'sentence'
, 'title'
, 'fields'
, 'menu_order'
);
套用琅琊榜里的一句话:“女人的感觉就是这么不讲道理”,此刻我的感觉也是百分百确认这些就是index.php支持的查询参数列表,没有再细看代码,直接修改nginx rewrite规则,没有修改哪怕是一行wordpress的代码,完整规则如下:
rewrite ^/(.*).html /index.php?name=$1 last;
rewrite ^/([0-9]+)/([0-9]+) /index.php?m=$1$2 last;
rewrite ^/tag/(.*) /index.php?tag=$1 last;
rewrite ^/page/([0-9]+) /index.php?paged=$1 last;
rewrite ^/author/(.*) /?author_name=$1 last;
rewrite ^/category/(.*) /?category_name=$1 last;
all bingo!!!
彩蛋:
查问题的过程中,发现了一个叫wp-json的东西,可以通过json查询相应内容,如果想开发wordpress的app,这个一定用的上。