以往幾年我的部落格網址樣式都是這樣:
http://blog.roga.tw/YYYY/MM/DD/POST_ID
作法是寫 rewrite rule 把 HTTP request 導給 WordPress 的 index.php 並且在後台的 Permalink Settings 採用 Custom Structure ( /%year%/%monthnum%/%day%/%post_id% ) 。
這樣好處就是簡單而且簡短,當時有不少用 WordPress 的朋友都用這種方法改寫網址,但缺點就是對搜尋引擎和訪客都不友善。所以,其實比較好的表示方式是 Permalink Settings 內建的 Month and name 格式。例如:http://blog.roga.tw/2008/05/james-blunts-live-concert-in-taipei/,這種格式可以直接從網址看出發文日期,也可以看出文章標題,而且和 http://blog.roga.tw/2008/05/18/581 是同一篇文章!
由於這個部落格已經有不少網址「流落在外」了,所以更換網址結構的時候,必須要寫個 Mapping 的機制,以避免文章找不到。
以下是我寫的小程式,存檔放到 plug-in 的目錄就可以解決新舊網址 Mapping 的問題 (當然,你的目錄結構也得和我以前一樣),程式採用 WordPress Native 的 Function 實做,設定也是拿 WordPress 定義的常數,所以不用擔心 hard code 的問題,如果不想用,在後台管理 plug-in 的地方也可以解除安裝。
以下是程式碼:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 |
<?php /* Plugin Name: roga's url hotfix Plugin URI: http://blog.roga.tw/2011/02/%E5%8A%A0%E5%BC%B7%E9%83%A8%E8%90%BD%E6%A0%BC%E7%9A%84-seo/ Description: redirect http requests. Version: 0.2 Author: roga Author URI: http://blog.roga.tw License: GPL v2 */ function roga_wrap() { GLOBAL $wpdb; $request_uri = trim(getenv('REQUEST_URI'), '/'); $array = explode('/', $request_uri); $status = TRUE; foreach($array as $row) { if( ! is_numeric($row) && ! empty($row)) $status = FALSE; } if(count($array) != 4 || $status != TRUE) return NULL; $post_id = (int) $array[3]; // http://blog.roga.tw/2011/02/16/2484 $wp_result = $wpdb->get_row("SELECT `post_type`, `post_name`, `post_date` FROM `$wpdb->posts` WHERE `ID` = $post_id "); if( ! isset($wp_result)) return NULL; $post_type = $wp_result->post_type; $post_name = $wp_result->post_name; $post_date = $wp_result->post_date; if($post_type == 'revision') return NULL; $time = strtotime($post_date); $year = date('Y', $time); $month = date('m', $time); // old: /%year%/%monthnum%/%day%/%post_id% // new: /%year%/%monthnum%/%postname%/ $new_request_uri = "/$year/$month/$post_name"; $http_host = getenv('HTTP_HOST'); $logfile = WP_CONTENT_DIR . "/cache/wp-roga-redirect.log"; if(file_exists($logfile)) file_put_contents($logfile, sprintf("[%s] %s -> %s / %s " . PHP_EOL, date_i18n("Y-m-d H:i:s"), $request_uri, urldecode($new_request_uri), getenv('HTTP_USER_AGENT')), FILE_APPEND); if (substr(PHP_SAPI, 0, 3) == 'cgi') header("Status: 301 Moved Permanently"); else header("HTTP/1.1 301 Moved Permanently"); header("Location: http://$http_host$new_request_uri"); exit(); } add_action('init', 'roga_wrap'); |
update:
謝謝 appleboy 的 patch ,修改一下一些錯誤。
1. 主要是加強判斷網址 blog.roga.tw/2011/02/17/2542 和 blog.roga.tw/2011/02/17/2542/ 兩者的差異 (trailing slash)
2. 最下面送 Header 的地方新增支援 CGI 和 Apache Handler (php module) 兩種,原本是只有支援 CGI, 因為我用 Fast-CGI
3. 上面的程式已經有 patch 過了~~
hi, 用了一下你寫的 plugin,有一個小 bug
如果當網址 http://blog.wu-boy.com/2011/02/17/2542 這沒有問題
但是如果是 http://blog.wu-boy.com/2011/02/17/2542/ 就會出問題了,不會進行導頁的動作
我改了 patch 檔案了,放在 http://blog.wu-boy.com/2011/02/wordpress-plugin-seo/ 裡面,給你參考看看
Thanks a lot. 沒考慮到 trailing slash 😀