WordPressをMT(Movable Type)形式でエクスポートしてブログをお引越し。

wordpressで書いていたブログを、はてなに引っ越すことにしました。

はてなで既存ブログデータをインポートするには、Movable Type形式(MT形式)でデータをエクスポートする必要があります。

今使用しているwordpressのバージョンは2.6で、MT形式でデータをエクスポートするために、WordPressExportというプラグインを使用しました。

プラグインのインストール

インストール方法などはこちらをご覧ください

プラグインのインストール後、管理画面の「設定」タブから「Export」をクリックすると、MT形式でデータ表示されるはずでしたが、何も出てきませんでした。

プラグインの修正

調べてみると、MT.php内21行目付近の、SQLを発行している部分で、エラーがでていることがわかりました。



MT.phpの21行目付近

$query = "SELECT $wpdb->posts.post_date, $wpdb->posts.post_content, $wpdb->posts.post_title, $wpdb->users.user_nickname, $wpdb->posts.post_status, $wpdb->comments.comment_author,  $wpdb->comments.comment_content, $wpdb->comments.comment_author_email,  $wpdb->comments.comment_author_url,  $wpdb->comments.comment_date,  $wpdb->post2cat.category_id, $wpdb->categories.cat_name FROM $wpdb->comments RIGHT  OUTER  JOIN  $wpdb->posts  ON (  $wpdb->comments.comment_post_ID  =  $wpdb->posts.ID  ) LEFT  OUTER  JOIN  $wpdb->users  ON (  $wpdb->posts.post_author  =  $wpdb->users.ID  ) LEFT OUTER  JOIN  $wpdb->post2cat  ON (  $wpdb->posts.ID  =  $wpdb->post2cat.post_id ) LEFT OUTER JOIN $wpdb->categories ON ($wpdb->post2cat.category_id = $wpdb->categories.cat_ID) ";


また、エラーがでている部分はeval()関数で実行されていたので、特にエラーなど出現せず、単に出力がない状態となっていたのです。

SQLをダンプすると以下のようになっていました。

SELECT
  wp_posts.post_date,
  wp_posts.post_content,
  wp_posts.post_title,
  wp_users.user_nicename,
  wp_posts.post_status,
  wp_comments.comment_author,
  wp_comments.comment_content,
  wp_comments.comment_author_email,
  wp_comments.comment_author_url,
  wp_comments.comment_date,
  wp_post2cat.category_id,
  wp_categories.cat_name
FROM
  wp_comments
RIGHT  OUTER  JOIN
  wp_posts
ON (
  wp_comments.comment_post_ID  =  wp_posts.ID
)
LEFT  OUTER  JOIN
  wp_users
ON (
  wp_posts.post_author  =  wp_users.ID
)
LEFT OUTER  JOIN
  wp_post2cat
ON (
  wp_posts.ID  =  wp_post2cat.post_id
)
LEFT OUTER JOIN
  wp_categories
ON (
  wp_post2cat.category_id = wp_categories.cat_ID
) 


このSQLでは、wp_categoriesと、wp_post2catというテーブルが見つからないためにエラーが発生しています。

いま使っているwordpress2.6では、これらのテーブルはありませんでした。
ただ、古いバージョンにはあったようなので、どこかのアップデートの段階でなくなったのだと思います。

プラグインが古くて、バージョンアップに対応していなかったのでしょうかね。

ということで、wp_categoriesとwp_post2catテーブル関連部分(SELECTとJOINのところ)、およびデータの書き出し部分で関係しているところを削除しました。

結果、SQLの部分は以下のようになりました。

$query = "SELECT $wpdb->posts.post_date, $wpdb->posts.post_content, $wpdb->posts.post_title, $wpdb->users.user_nicename, $wpdb->posts.post_status, $wpdb->comments.comment_author,  $wpdb->comments.comment_content, $wpdb->comments.comment_author_email,  $wpdb->comments.comment_author_url,  $wpdb->comments.comment_date  FROM $wpdb->comments RIGHT  OUTER  JOIN  $wpdb->posts  ON (  $wpdb->comments.comment_post_ID  =  $wpdb->posts.ID  ) LEFT  OUTER  JOIN  $wpdb->users  ON (  $wpdb->posts.post_author  =  $wpdb->users.ID  ) ";


さて、修正して再度エクスポートをしてみたのですが、まだ何もでてきませんでした。

次に怪しい部分は、23行目あたりからの、実際にクエリを投げてデータを取得する部分です。


MT.phpの23行目付近

$result = $wpdb->query($query);
if ($result){
    for ($i = 0; $i < $result; $i++) {
	    $row = $wpdb->get_row(null,OBJECT,$i);

        if ($prev_entry == $row->post_date) {
            ...


$wpdp->query()でデータを取得して、$resultに取得した行数が帰ります。
それをfor文でまわして$wpdb->get_row()で一行づつ処理しようとしたのだと思います。

しかし、$wpdb->get_row()も途中で実装が変わったのか、第一引数にnullが指定されてしまうと、nullしかかえって来ません。


wp-includes/wp-db.php 733行目付近

function get_row($query = null, $output = OBJECT, $y = 0) {
    $this->func_call = "\$db->get_row(\"$query\",$output,$y)";
    if ( $query )
        $this->query($query);
    else
        return null;

    if ( !isset($this->last_result[$y]) )
        return null;

    if ( $output == OBJECT ) {
        return $this->last_result[$y] ? $this->last_result[$y] : null;
    } elseif ( $output == ARRAY_A ) {
        ...


nullのかわりにSQL文を指定するのが正しい使用方法です。

ただ、$wpdb->get_row()は本当に一行だけ取得したい場合に使用するべきです。
なぜなら、$wpdb->get_row()は内部で$wpdb->query()を呼び出しているので、毎回クエリが発生してしまうので効率が悪いためです。

その代わりに、今回のように一度にデータを取得して、結果をfor文でまわすような場合には、$wpdb->get_result()を使用するのが正しいようです。

上記を踏まえ、以下のように処理を変更しました。

 //$result = $wpdb->query($query);
    $result = $wpdb->get_results($query, OBJECT);
    if ($result){
		//for ($i = 0; $i < $result; $i++) {
		foreach($result as $i=>$row) {
			//$row = $wpdb->get_row(null,OBJECT,$i);
			if ($prev_entry == $row->post_date) {
			...


これのほかに、こちらにでも書いてありますが、エントリーの区切りが

--------
--------


のになってしまう件についても、

-----
--------


になるように修正しました。


MT.php 73行目付近

//$output .=  "--------\n";
$output .=  "-----\n";


これでようやくMT形式でエクスポートできました。

ただし、ドラフト版もひとつのエントリーとして出力されてしまい、はてなではこれらもひとつの記事として公開されていて、具合が悪いです。

ということで、公開記事だけエクスポートされるように、wp_posts.post_status = 'publish'という条件をSQL文に付け加えました。

$query = "SELECT $wpdb->posts.post_date, $wpdb->posts.post_content, $wpdb->posts.post_title, $wpdb->users.user_nicename, $wpdb->posts.post_status, $wpdb->comments.comment_author,  $wpdb->comments.comment_content, $wpdb->comments.comment_author_email,  $wpdb->comments.comment_author_url,  $wpdb->comments.comment_date  FROM $wpdb->comments RIGHT  OUTER  JOIN  $wpdb->posts  ON (  $wpdb->comments.comment_post_ID  =  $wpdb->posts.ID  ) LEFT  OUTER  JOIN  $wpdb->users  ON (  $wpdb->posts.post_author  =  $wpdb->users.ID  ) WHERE $wpdb->posts.post_status ";


これで、公開されたバージョンのみインポートすることができました(手作業で修正しなければならないことがちょっと残っていますが...)。

修正したWordPressExportプラグインのMT.phpこちらから



ちなみに、以前のブログですが、普通の日記を更新していこうと思います。
技術的な記事はここで、それ以外は以前のところで、という棲み分けになります。