MovableType3(DB4版)とPHP製システムを連携させる

こんにちは、バズー株式会社、開発チームリーダーの清水です。

セレブスタイルのシステムはPHPで構築されています。ただ、CMS機能はMovable Typeのほうがよくできているので、Movable TypePHPを連携する必要があります。

そこで問題になるのがデータベース。いろいろ問題があってMovable Type 4が使えず、Movable Type3と連携する必要があったのですが、Movable Type3はDB4というデータベースを使っています。DB4は、MySQLPostgreSQLのようにSQLを扱うことができません。

Movable Type3のデータは以下の図のようになっています。

mtdb4.png

解説するとこんな感じです。

SERG/4バイト/接頭辞
キーの長さ/4バイト
キー/任意バイト
データの長さ/4バイト
データ/任意バイト


以下キー、データの連続

PHPでDB4のデータを読み込むサンプルです。dba_xxx 関数を使うためにはPHPのDBA拡張機能がインストールされている必要があります。

<?php
// MTのデータベース(DB4)を解析する
function _thaw_mt_1($frozen) {
  $thawed = array();
  $len = strlen($frozen);
  $pos = 4;
  while ($pos < $len) {
    $slen = unpack('N', substr($frozen, $pos, 4));
    $col = $slen['1'] ? substr($frozen, $pos+4, $slen['1']) : '';
    $pos += 4 + $slen['1'];
    $slen = unpack('N', substr($frozen, $pos, 4));
    $col_val = substr($frozen, $pos+4, $slen['1']);
    $pos += 4 + $slen['1'];
    $thawed[$col] = mb_convert_encoding($col_val, "SJIS-win", "UTF-8");
  }
  return $thawed;
}
// インポート開始
function execute_import() {
  // リミッター解除
  ini_set('memory_limit','-1');
  // データベースを開く
  $id = dba_open("/somewhere/entry.db", "r", "db4");
  // エラーチェック
  if (!$id) {
    echo "dba_open failed\n";
    exit;
  }
  // データ一覧
  $entries = array();
  // 最初のキーを取得
  $key = dba_firstkey($id);
  $entry = _thaw_mt_1(dba_fetch($key, $id));
  if ($entry['blog_id'] == 2 || $entry['blog_id'] == 3 || $entry['blog_id'] == 4) {
    $entries[] = $entry;
  }
  // キーをすべて取得
  while ($key != false) {
    if (true) {
      // エントリーを取得
      $entry = _thaw_mt_1(dba_fetch($key, $id));
      if ($entry['blog_id'] == 2 || $entry['blog_id'] == 3 || $entry['blog_id'] == 4) {
        $entries[] = $entry;
      }
    }
    $key = dba_nextkey($id);
  }
  // データベースを閉じる
  dba_close($id);
  // エントリー一覧を表示
  print_r($entries);
}
execute_import();

実行するとエントリー一覧が表示されます。
1つのエントリーは以下のような構成になっています。

author_id・・・著者管理ID
text・・・本文
title・・・件名
allow_comments・・・コメント許可?
basename・・・不明
allow_pings・・・PING許可?
modified_on・・・変更日時
blog_id・・・ブログ管理ID
to_ping_urls・・・PING送信先
excerpt・・・不明
status・・・詳細不明
convert_breaks・・・行末の改行の扱い?
created_on・・・作成日時
id・・・エントリー管理ID
text_more・・・本文の続き

アクセスの度にエントリー一覧を取得すると、パフォーマンスが悪いので、バッチで取得して他のデータベースに格納するのが現実的だと思います。