{Blog 系統轉移} b2evolution migrate to wordpress import script.

從某一個應用系統 (或資料庫系統)要把資料轉移到另一個應用系統 (或資料庫系統),這個轉移的過程稱之為 “Migration” (相對地,若是同一系統的版本更新,則稱之為 Upgrade)。

上一個月,要從原來 b2evolution Blog 系統轉移 (migrate)到 wordpress 系統時,就如同當初我從 MT 轉移到 b2evolution 一樣,官方的系統均有提供 import (載入) 的 script 檔。 只是, MT 轉 b2evolution 時,當時因為資料結構比較單純,所以完全不用作任何修正,透過 import 工具程式一下子就轉好了;但是,這兩三年來, b2evolution 系統相當積極,版本更新極快,而每一次大版本的更新,必然會變動到 DB Schema,這使得 wordpress 所提供可以 import from b2evolution 的 script 檔,不可能不作修改就可以順利完成轉移作業。

wordpress 官方所提供對各大 Blog 系統的 import script 檔在此:Importing Content。 不過,我真的挺懶,想說若能找到無痛地可以從我現在 b2 1.10.3 版本 → wordpress 2.71 的網友加持修改版,那就更省事了。 結果呢,花了大半天的時間,是有找到啦,像這篇: Import From B2evolution(2.4.6) to WordPress (2.7)。 只是,要收費耶!! 含售後客服要價 50 USD。 其實啊,這價錢是算便宜的啦,當初我擔任某家公司的 Oracle DBA 時,幫企業客戶作轉檔的話,起碼是 10 數倍以上收費起跳的呢。

不過,想想還是乾脆又自己來動手 DIY 好了。 其實轉檔的原理相當簡單,就是把 Source Schema 對應 (mapping) 到 Target Schema 就對了。 b2evolution 有 31 個表格;wordpress 則只有 10 個 (非常欣賞它的結構簡潔)! 怎麼會差這麼多? 主因就是前者是被設計來服務多個部落格用戶的,而後者僅設定單一的部落格,所以前者儲存了非常多的統計數據,而這些,其實是不用轉移的。

轉移的核心會是什麼? 當然就是本文內容了。 本文就是包含 Post 內文 (content)與迴響 (comment),一篇內文會包含 0 到 多篇迴響,非常典型的 “Master-Detail” 表格結構,一般就是會有兩個表格個別儲存並以 Key (primary-key to foreign key)來關聯了。 所以只要找出含有 “_post” 字串的表格,大部份就是儲存 Post 內文的主表了。 再以此為中心,把一些如類別 (category)、帳號等額外資訊,給一一的加進來即可。

轉檔的寫法百百種,可以利用 stored-procedure、利用 C#/VB.NET、PHP、Perl 等機制來轉寫轉檔程序。 事實上,對資料結構與 SQL 語法精通的真正高手來說,只要寫個 SQL 陳述 (statement)甚至就可以轉移了。 嗯,我那個 partner Ringle 就是精通此道,他對資料庫的掌握度,我仍是沒有看到一個比他更強悍的。 可惜,他可不幫我作這種小事,而他收費可更是不便宜。 所以呢,我還是又繞回來,下載回來 wordpress 官方的 import script 程式,當然是利用 php 撰寫的,再以此作為轉移程式的 “骨架 (skeleton)”,然後慢慢地調整 SQL 陳述,修改表格與欄位、資料型態等。 呵呵,比想像得簡單,我採用漸進調整的方式作業,大概反覆轉移了有四、五次之多,至最終轉到我滿意正確的結果,大約也才耗上半天的時間而已。


其實,我並沒有把類別轉過來,原因是我覺得原來我規劃的分類太過繁雜了,所以我想乾脆重新針對每一篇文章來指定類別,同時,也來設定 wordpress 相當流行的 標籤 (Tag)。 所以,每一篇轉移過來的文章都是 “未分類”,然後呢,我又再花上了有近兩天的時間,共有近1000 篇,然後一篇一篇地重新指定類別與標籤,順便再對較舊的文章重新排版。 這些可都是 “硬功夫”,沒有訣竅可以幫你的。

我 “客製化” 化過的轉檔 PHP script,這裡就同時作個保留紀念,如果有興趣的讀者們也可以下載參考 (下載回來後把後面的 .txt 改為 .php 即可): migrate_b2-to-wp.txt

上述所提真正的核心程式碼,其實是下面這一段程式碼。 有其它 Blog 系統想轉移至 wordpress 的讀者們,多少可以作個參考。

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
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
// get entries for blog
echo "Importing Entry records ... <BR />";
$sql = "SELECT * FROM evo_posts";
$result = mysql_query($sql,$resB2) or die("Invalid query: " . mysql_error() . "<BR /> SQL : " . $sql);
if ($result) {
    $cnt = 0;
    $cntCom = 0;
    $cntCat = 0;
    while ($row = mysql_fetch_array($result, MYSQL_ASSOC)) {
        // author ID must be switched to new author ID
        //$aid = $arUser[$row['post_author']];
        $aid = 1; //Set to Admin User.
 
        // category ID must be switched to new category ID
        //$cid = $arCat[$row['post_category']];
			//if (!$cid) {
			//	$cid = '1';
			//}
			$cid = 0; //設定為 "未分類"
 
        // status mapping
        $stat = $row['post_status'];
        if ($stat == 'published') {
            $stat = 'publish';
        } else if ($stat == 'deprecated') {
            $stat = 'publish';
        } else if ($stat == 'protected') {
            $stat = 'private';
        } else if ($stat == 'private') {
            $stat = 'private';
        } else if ($stat == 'draft') {
            $stat = 'draft';
        }
 
        // update urls in the post content
        $post_content = $row['post_content'];
        $post_content = str_replace($filepath_b2, $filepath_wp, $post_content);
 
        $sql = trim(str_replace("\n","","INSERT INTO `". $wp_pref ."posts` ".
            "(`post_author`,`post_date`,`post_content`,`post_title`,`post_category`,`post_status`)" .
            " VALUES ('".$aid."','".$row['post_issue_date']."','".mysql_escape_string($post_content)."','" .
            mysql_escape_string($row['post_title'])."','".$cid."','".$stat."');"));
			echo "$sql <br />";
        $q = mysql_query($sql, $resWP) or die("Invalid query: " . mysql_error() . "<BR /> SQL : " . $sql);
        $id = mysql_insert_id($resWP);
        $eid = $row['ID'];
        $cnt = $cnt + 1;
 
        // get comments for entry
        $sql = "SELECT * FROM evo_comments WHERE comment_post_ID=" . $eid;
        $res = mysql_query($sql, $resB2) or die("Invalid query: " . mysql_error() . "<BR /> SQL : " . $sql);
        if ($res) {
            while ($row = mysql_fetch_array($res, MYSQL_ASSOC)) {
                $sql = trim(str_replace("\n","","INSERT INTO `". $wp_pref ."comments` ".
                    "(`comment_post_ID`,`comment_author`,`comment_author_email`," .
                    "`comment_author_url`,`comment_author_IP`,`comment_date`," .
                    "`comment_content`,`comment_karma`)" .
                    " VALUES ('".$id."','" . mysql_escape_string($row['comment_author']) . "','" . mysql_escape_string($row['comment_author_email']) .
                    "','" . mysql_escape_string($row['comment_author_url']) . "','" . $row['comment_author_IP'] . "','" . $row['comment_date'] .
                    "','" . mysql_escape_string($row['comment_content'])."','". $row['comment_karma'] ."');"));
                $q = mysql_query($sql, $resWP) or die("Invalid query: " . mysql_error() . "<BR /> SQL : " . $sql);
                $cntCom = $cntCom + 1;
            }
        }
        // get categories for entry
			$cntTmp = 0;
			$sql = "SELECT * FROM evo_postcats WHERE postcat_post_ID=" . $eid;
			$res = mysql_query($sql, $resB2) or die("Invalid query: " . mysql_error() . "<BR /> SQL : " . $sql);
			if ($res) {
				while ($row = mysql_fetch_array($res, MYSQL_ASSOC)) {
					$cid = $arCat[$row['postcat_cat_ID']];
					$sql = trim(str_replace("\n","","INSERT INTO `". $wp_pref ."post2cat` ".
						"(`post_id`,`category_id`)" .
						" VALUES ('" . $id . "','" . $cid . "');"));
					$q = mysql_query($sql, $resWP) or die("Invalid query: " . mysql_error() . "<BR /> SQL : " . $sql);
					$cntCat = $cntCat + 1;
					$cntTmp = $cntTmp + 1;
				}
			}
			if ($cntTmp == 0) {
				// No categories defined in b2evo - put it in the default category
				$sql = trim(str_replace("\n","","INSERT INTO `". $wp_pref ."post2cat` ".
					"(`post_id`,`category_id`)" .
					" VALUES ('" . $id . "','1');"));
				$q = mysql_query($sql, $resWP) or die("Invalid query: " . mysql_error() . "<BR /> SQL : " . $sql);
				$cntCat = $cntCat + 1;
			}
    }
    echo $cnt . " Entry record(s) imported! <BR />";
    echo "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;" . $cntCom . "Comment record(s) imported! <BR />";
    echo "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;" . $cntCat . "Entry Category record(s) imported! <BR />";
} else {
    echo "No Entry records found!<BR />";
}
mysql_close($resB2);
mysql_close($resWP);
echo "That's all folks!";
break;

文章導覽

   

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *