WordPressのデータをmicroCMSに移行

こんにちは、t-tomoです。
今回WordPressのユーザーとブログのデータをmicroCMSに移行する作業をしたので手順を書き残します。

方法はいくつかあると思いますが、今回は①を選択しました。
①自分のPCを基点として、WordPressのデータをダウンロード、PCで移行プログラムを実行、microCMSにデータをアップロード
②WordPressサーバーを基点として、WordPressサーバーで移行プログラムを実行、microCMSにデータをアップロード
③クラウドサーバーを基点として、WordPressのデータをダウンロード、クラウドサーバーで移行プログラムを実行、microCMSにデータをアップロード

手順

microCMS のマイページにて X-MICROCMS-API-KEY を作成

この際データ転送を受け付ける為に POST を有効化

APIスキーマの設定

ユーザーデータと記事データをWordPressのデータベースからXML形式でエクスポート

画像ディレクトリをWordPressのサーバーからエクスポート

ユーザーデータと記事データと画像データをPCの作業ディレクトリに配置

ディレクトリツリー

ユーザーデータをアップロードするPHPプログラム

ユーザーデータXMLファイルの中身を取得して配列を作成

ユーザー情報(名前や役割)をmicroCMSのAPIスキーマの形式に変換

この際ユーザー情報に紐付く画像を後でmicroCMSに手動アップロードするための別ディレクトリにコピー

microCMS APIのURL と X-MICROCMS-API-KEY を設定

CURLでPOST送信

<?php
/*
 * XMLデータからユーザー情報を取得
 * 以下をユーザー数分繰り返す
 * プロフィールの画像パスを基にuploadsディレクトリから使用する画像データのみをuser_imagesディレクトリにコピー
 * ユーザー情報をmicroCMSにPOST送信
 *
 * microCMSのAPIで画像の登録不可のためダッシュボードから手動で設定
 * https://help.microcms.io/ja/knowledge/add-image-api
 */

echo "ユーザーデータの移行を開始します。\n";
$users = simplexml_load_string(file_get_contents("./data/users.xml"));
echo count($users) . "件のユーザーデータを送信します。\n";

foreach ($users as $user) {
    echo $user->display_name . "のデータを送信します。\n";
    $wp_image_path = (string)$user->tbl_user_avatar;
    $local_image_path = strrchr($wp_image_path, "uploads");
    $image = file_get_contents($local_image_path);
    $cms_path_array = explode("/", $local_image_path);
    file_put_contents("user_images/{$user->last_name}_{$cms_path_array[1]}_{$cms_path_array[2]}_{$cms_path_array[3]}", $image);
    $data = [
        "id" => "00" . $user->user_id, // WordPressのレコードIDを引き継ぐが3桁以上必要なのでゼロパディング
        "japanese_name" => (string)$user->display_name,
        "english_name" => $user->first_name . " " . $user->last_name,
        "position" => (string)$user->position,
        "profile_image_alt" => (string)$user->first_name,
        "description" => trim((string)$user->description),
    ];

    $url = "https://okun.microcms.io/api/v1/team";
    $headers = ["Content-Type: application/json", "X-MICROCMS-API-KEY: *****"];

    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $url); // URLを指定
    curl_setopt($ch, CURLOPT_POST, true); // HTTP POSTを指定
    curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); // HTTPヘッダを指定
    curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data)); // POSTで送信するデータを指定
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); // 戻り値に文字列を指定
    $html = curl_exec($ch);
    echo $html . "\n";
    curl_close($ch);
}

ブログデータをアップロードするPHPプログラム

課題2つ

WordPressの記事がHTMLで保存されていること
microCMSで新しく記事を書く際もメンバーにHTMLで書いてもらう訳にはいかないため、移行前と移行後の記事で扱いを分ける必要がある。
microCMSのヘルプセンターの案内に従いカスタムフィールドを設定した。
WordPressの記事(HTML)とmicroCMSの記事(リッチテキスト)はフロント側で表示の分岐を実装した。

microCMSのメディアのURLはアップロード後にランダム値が設定されること
記事内で使われている画像パスを変更(WordPressのURL → microCMSのURL)したいなら、画像を先にmicroCMSのメディアにアップロードしておく必要がある。

変更前
変更後

よってプログラムを2つに分割

1つ目のPHPプログラム

ブログデータXMLファイルの中身を取得して配列を作成

ブログの記事内に含まれる画像パスに紐付く画像を後でmicroCMSに手動アップロードするための別ディレクトリにコピー

<?php
/*
 * XMLデータからユーザー情報を取得
 * 以下をユーザー数分繰り返す
 * プロフィールの画像パスを基にuploadsディレクトリから使用する画像データのみをcms_imagesディレクトリにコピー
 * ユーザー情報をmicroCMSにPOST送信
 *
 * microCMSのAPIで画像の登録不可のためダッシュボードから手動で設定
 * https://help.microcms.io/ja/knowledge/add-image-api
 *
 * 画像URLの変更
 * https://blog.microcms.io/add-media-get-api
 */

$articles = simplexml_load_string(file_get_contents("./data/article.xml"));
echo count($articles) . "件の記事画像データを抽出します。\n";

$thumbnail_suffix = 0;

foreach ($articles as $article) {
    echo $article->post_title . "の画像データを抽出します。\n";

    $wp_thumbnail_path = (string)$article->thumbnail_path;
    $local_thumbnail_path = strstr($wp_thumbnail_path, "uploads");
    $thumbnail_image = file_get_contents($local_thumbnail_path);
    $cms_thumbnail_path_array = explode("/", $local_thumbnail_path);
    $thumbnail_suffix++;
    file_put_contents("article_thumbnail_images/thumbnail_{$thumbnail_suffix}_{$cms_thumbnail_path_array[1]}_{$cms_thumbnail_path_array[2]}_{$cms_thumbnail_path_array[3]}", $thumbnail_image);

    // ブログ記事を取得
    $content = (string)$article->post_content;

    // ブログ記事内で画像を参照する部分を正規表現で抽出
    preg_match_all('/src="https:\/\/o-kun\.com\/wp-content\/uploads\/(.*)(png|jpg|jpeg|gif)"/i', $content, $matches);

    foreach ($matches[0] as $match) {
        $pathArray = explode("/", $match);
        $local_content_path = str_replace('"', "", strstr($match, "uploads"));
        $content_image = file_get_contents($local_content_path);
        $image_name = str_replace(["/", "uploads_"], ["_", ""], $local_content_path);
        file_put_contents("article_content_images/" . $image_name, $content_image);
    }
}

ブログの画像をmicroCMSに手動アップロード

2つ目のPHPプログラム

ブログデータXMLファイルの中身を取得して配列を作成

microCMSのメディア情報を一括取得

ブログ情報をmicroCMSのAPIスキーマの形式に変換
この際にブログ内の画像のパスを変更(WordPressのURL → microCMSのURL)

microCMS APIのURL と X-MICROCMS-API-KEY を設定

CURLでPOST送信

<?php
/*
 * microCMSに保存されているメディア情報を取得
 * 記事データのXMLファイルを読み込み
 * ブログ記事内の画像参照パスドメインをWordPressからMicroCMSに書き換え
 * POST APIを実行
 *
 * 画像URLの変更について
 * https://blog.microcms.io/add-media-get-api
 */

echo "メディアリストを取得します。\n";
$media_url = "https://okun.microcms-management.io/api/v1/media?limit=10000";
$headers = ["Content-Type: application/json", "X-MICROCMS-API-KEY: *****"];
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $media_url); // URLを指定
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); // HTTPヘッダを指定
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); // 戻り値に文字列を指定
$html = curl_exec($ch);
$result = json_decode($html, false);
$media_array = $result->media;
curl_close($ch);
echo $result->totalCount . "件のメディア情報を取得しました。\n";

$articles = simplexml_load_string(file_get_contents("./data/article.xml"));
echo count($articles) . "件の記事データを送信します。\n";
foreach ($articles as $article) {
    echo $article->post_title . "の記事データを送信します。\n";

    // ブログ記事を取得
    $content = (string)$article->post_content;

    // ブログ記事内で画像を参照する部分を正規表現で抽出
    preg_match_all('/src="https:\/\/o-kun\.com\/wp-content\/uploads\/(.*)(png|jpg|jpeg|gif)"/i', $content, $matches);
    // 画像パス置き換え用の配列を作成
    $patterns = [];
    $replaces = [];
    foreach ($matches[0] as $match) {
        $patterns[] = "/" . preg_replace("/\//", "\/", $match) . "/";
        $pathArray = explode("/", $match);
        $paths = array_reverse($pathArray);
        $local_content_path = str_replace('"', "", strstr($match, "uploads"));
        $content_image = file_get_contents($local_content_path);
        $image_name = str_replace(["/", "uploads_"], ["_", ""], $local_content_path);
        foreach ($media_array as $media) {
            $full_path_array = explode("/", $media->url);
            if ($image_name === end($full_path_array)) {
                $replaces[] = 'src="' . $media->url . '"';
            }
        }
        file_put_contents("article_content_images/" . $image_name, $content_image);
    }

    $html_content = preg_replace($patterns, $replaces, $content);

    $data = [
        "title" => (string)$article->post_title,
        "content_field" => [["fieldId" => "html", "html" => $html_content]],
        "thumbnail_alt" => (string)$article->post_title,
        "author" => "00" . $article->user_id
    ];

    $url = "https://okun.microcms.io/api/v1/blog";
    $headers = ["Content-Type: application/json", "X-MICROCMS-API-KEY: *****"];
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $url); // URLを指定
    curl_setopt($ch, CURLOPT_POST, true); // HTTP POSTを指定
    curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); // HTTPヘッダを指定
    curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data)); // POSTで送信するデータを指定
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); // 戻り値に文字列を指定
    $html = curl_exec($ch);
    echo $html . "\n";
    curl_close($ch);
}

注意事項

  • microCMSのHobby(無料)の場合、データ転送量が20GB/月のためプログラムの開発、検証段階では1〜3記事で進める事を推奨
  • microCMSにメディア(画像データ)をアップロードする際、2022年11月23日現在APIは利用できず、管理画面にて手動操作が必要

メディアパスについては、ランダムとなるため、規則性はない仕様となっております。
画像をまとめてアップロードいただいたあと、メディアの取得APIを利用すると、画像のフルパスが取得できます。

microCMSサポートの回答

参考記事

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

ABOUTこの記事をかいた人

とにかくメガネ。「眼鏡をかけている」とか「眼鏡が好き」とかではなく、本体がメガネ。なのでメガネを取ったら消滅してしまう。