PHPでWordPressの投稿データをSQLiteへエクスポートする
WordPressの基本機能で[ツール]の[エクスポート]から記事データをXMLファイルへ出力する機能はあるのですが、なぜか記事の最終更新日が出力されません。
投稿日は出力されるので運用によっては問題ないのかもですが、うちのブログのようにちょいちょい過去記事を見直して修正する場合、記事の最終更新日がないとちょっと管理しづらい。
また、以前に「バリューサーバーのMySQLが落ちやすい」で書いたとおり、WordPressの世界シェアは33%と圧倒的なものの、サーバーへの負荷が高く、ページが重くなりがちなのでWordPressから静的ページや独自のCMSへ移行する企業も増えているようです。
このブログもそのうち自前のCMSへ移行しようかなぁ、と検討中なので、今のうちにWordPressで書いた記事データをsqlite等にコンバートできる仕組みを考えておこうと思いました。
WordPressのwp_postsから取得するデータ
というわけで、WordPressが使っているMySQLデータベースのwp_postsテーブルから直接記事データを吸い出しちゃおう、という話ですが、テーブルのどの項目がどういう意味なのか知らないと抜き出せませんよね。
ざっくり見たところ、wp_postsの中身はこんな感じ。
post_title | 記事タイトル |
post_content | 本文 |
post_date | 投稿日 |
post_modified | 最終更新日 |
post_name | パーマリンク |
また、wp_postsテーブルには下書きデータなども含まれるため、post_statusとpost_typeに条件を付けてあげる必要がありそうです。
具体例
SELECT * FROM wp_posts WHERE post_status='publish' AND post_type='post'
このSQL文で公開済の投稿データが全て取得できるハズ。
PHPでWordPressのwp_postsを読み取る例
PHPのPDOで書くならこんな感じでしょうか。
//接続情報
$cfg['WP_PDO_DSN'] = 'mysql:host=localhost;charset=utf8mb4;port=3306;dbname=[データベース名];';
$cfg['WP_PDO_USER'] = '[ユーザー名]';
$cfg['WP_PDO_PASS'] = '[パスワード]';
//WordPressのデータを取得
$conn_wp = new PDO($cfg['WP_PDO_DSN'], $cfg['WP_PDO_USER'], $cfg['WP_PDO_PASS'],
array(PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
PDO::ATTR_EMULATE_PREPARES => true,
PDO::ATTR_STRINGIFY_FETCHES => false
));
$query = "SELECT * FROM wp_posts WHERE post_status='publish' AND post_type='post'";
$i = 0;
foreach ($conn_wp->query($query) as $row) {
$i++;
echo implode(" ", array($i, $row['post_date'], $row['post_modified'], $row['post_title'])).'<br>';
}
うちの環境で試した限りではこれでちゃんと必要な記事データが取得できました。
PHPでWordPressの投稿データをsqliteに変換する
将来的にWordPressを静的コンテンツ(ただのHTML)へ一括変換するのなら、先述のPHPで取得したwp_postsをHTMLへ変換するだけの話ですが、実際は何らかの更新システム(自分で作った独自のCMS等)を用意すると思います。
そのとき、またMySQLを使うと同居している他サイトの影響を受ける可能性が高いかもなので、ひとまずsqliteへ変換してみることにしました。
まぁ変換といっても、単にMySQLからSELECT文でデータ取得して、sqliteにINSERTするだけのことですけども。
<?php
//接続情報
$cfg['WP_PDO_DSN'] = 'mysql:host=localhost;charset=utf8mb4;port=3306;dbname=[データベース名];';
$cfg['WP_PDO_USER'] = '[ユーザー名]';
$cfg['WP_PDO_PASS'] = '[パスワード]';
//sqliteへ接続
$conn_sqlite = new PDO('sqlite:blog.db');
//postsテーブルの作成
$query = '
CREATE TABLE IF NOT EXISTS posts (
ID integer PRIMARY KEY AUTOINCREMENT,
post_title text,
post_content text,
post_date datetime,
post_modified datetime,
post_name varchar(200))';
$conn_sqlite->query($query);
//WordPressのデータを取得
$conn_wp = new PDO($cfg['WP_PDO_DSN'], $cfg['WP_PDO_USER'], $cfg['WP_PDO_PASS'],
array(PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
PDO::ATTR_EMULATE_PREPARES => true,
PDO::ATTR_STRINGIFY_FETCHES => false
));
$query = "SELECT * FROM wp_posts WHERE post_status='publish' AND post_type='post'";
//sqliteへのINSERT文を準備
$stmt_sqlite = $conn_sqlite->prepare("INSERT INTO posts (post_title, post_content, post_date, post_modified, post_name) VALUES (?,?,?,?,?)");
$i = 0;
foreach ($conn_wp->query($query) as $row) {
$i++;
echo implode(" ", array($i, $row['post_date'], $row['post_modified'], $row['post_title'])).'<br>';
$param = array();
$param[] = $row['post_title'];
$param[] = $row['post_content'];
$param[] = $row['post_date'];
$param[] = $row['post_modified'];
$param[] = $row['post_name'];
$stmt_sqlite->execute($param);
}
?>
解説
sqliteは非常にシンプルでユーザー名とパスワードの指定すら必要なく(というかユーザー管理がない)、データベースをあらかじめ作っておく必要すらないため、
$conn_sqlite = new PDO('sqlite:blog.db');
という実にシンプルな書き方でDBへ接続できます。
ここでは blog.db というファイル名を指定していますが、このファイルがなければ作成し、すでにあればそこへ接続する動作となります。
そして、以下のSQL文を発行することで、postsテーブルを作成しています。
CREATE TABLE IF NOT EXISTS posts
これも IF NOT EXISTS と書かれているとおり、postsテーブルが存在しないときだけ作成する処理をしています。
WordPressのMySQLからの読み込み処理は先述と変わらず、読み込みループの前に $conn_sqlite->prepare でプリペアドステートメントを用意しています。
INSERT INTO posts (post_title, post_content, post_date, post_modified, post_name) VALUES (?,?,?,?,?)
ループの内部で毎回INSERT文を組み立てるのは非効率なので、あらかじめテンプレートとなるINSERT文を用意(プリペアド)し、ループ内部ではプレースホルダ(クエスチョンマークで書かれた部分)に記事タイトルや本文をセットしているわけです。
$param = array();
$param[] = $row['post_title'];
$param[] = $row['post_content'];
$param[] = $row['post_date'];
$param[] = $row['post_modified'];
$param[] = $row['post_name'];
$stmt->execute($param);
これだけでサクっとWordPressの投稿データ(wp_posts)をsqliteデータベースへエクスポートすることが出来ました。
まとめ
- WordPressの記事データは以下のSQL文で取得可能
SELECT * FROM wp_posts WHERE post_status='publish' AND post_type='post'
- wp_postsテーブルにあるそれぞれの項目は下記のとおり。
post_title 記事タイトル post_content 本文 post_date 投稿日 post_modified 最終更新日 post_name パーマリンク
これだけわかっていればsqliteに限らず、CSVへ変換したり、別のデータベースへ変換することも簡単に出来そう。
Web運営を長く続けるコツは更新処理の簡略化だと思うんですよね。