blogスタッフブログ
HOME > スタッフブログ > CMS >ComponentBlocksのデータを開発環境から本番環境にインポートした時のオブジェクトIDの扱い

ComponentBlocksのデータを開発環境から本番環境にインポートした時のオブジェクトIDの扱い

現状の課題

PowerCMS XのComponentBlocksで編集表示を「画像」「アセット」「リレーション」とした時、保存されるのは選択したオブジェクトのIDです。ただ、開発環境と本番環境がある場合、両環境でオブジェクトのIDが完全一致していることはまずありません。よって、記事を開発環境でCSVエクスポートし、本番環境でインポートしても、同じ画像が表示できないことになります。

カラムでタイプを「数値」、編集表示を「リレーション」としてアセットを選択できるようにしている場合(例えばog:image用画像)、CSVエクスポート時に保存されているIDを画像パスに変換し、インポート時に画像パスからIDに戻しているようなので、エクスポート・インポートを行っても紐付けは維持されます。ただ、ComponentBlocksは動作基盤が「カスタム編集タイプ」なので、そのような処理が行われていません。

製品として考えられる対策は、

  • 通常のカラム同様にIDをパス等に置き変える
  • ComponentBlocksでオブジェクトのIDではなくモデル名とUUIDを保存する

等が考えられますが、互換性等も考えるとなかなかすぐに開発の目処が立ちません。カスタム編集タイプが増える度に処理のバリエーションも増えていきそうです。(カスタム編集タイプ毎にクラス化すれば良いか…)

暫定の対策案

プラグインを利用してpre_importコールバックに対する処理を書き、インポート時に自動でオブジェクトIDを置換します。具体的には、ComponentBlocksのデータを解析し、アセット等のオブジェクトIDがあるカラムの値を置き変えを行います。開発環境と本番環境のID突き合わせ方法は手動・自動で色々考えられますが、一番簡易で間違いがなさそうなのはRESTful APIの利用です。

まず、ComponentBlocksのデータ中にあるアセットIDから開発環境のオブジェクトにアクセスし、オブジェクトのUUIDを取得します。そのUUIDを利用して本番環境のオブジェクトを特定しオブジェクトIDを書き換えます。事前にアセットをCSVインポートしておく必要があります。

public function pre_import_entry(&$cb, $app, &$obj, $original) {
    $client = ClientBuilder::create()
        ->setApplicationUrl('https://開発環境のURL/powercmsx/api/index.php');

    $block_edit_json_str = $obj->block_edit; // 保存データを取得
    if ($block_edit_json_str && $block_edit_json_str !== '[]') {
        $block_data = json_decode($block_edit_json_str);
        foreach ($block_data as &$block) {
            if ($block->type === 'Image') { // ブロックを判定
                $dev_env_asset = $client->getObject('asset', 1, (int) $block->asset_id, false, ['id', 'uuid']);
                $asset_uuid = $dev_env_asset->uuid; // UUIDを取得
                if (!$asset_uuid) continue;

                $prod_env_asset = $app->db->model('asset')->load(['uuid' => $asset_uuid], [], 'id');
                if (count($prod_env_asset) === 1) {
                    $block->asset_id = (int) $prod_env_asset[0]->id; // 現環境のオブジェクトIDに置き変え
                }
            }
        }
        $obj->block_edit(json_encode($block_data));
    }
}

PHPからRESTful APIにアクセスする際は、記事「RESTful APIを用いたユーザー認証とPHP Clientのご紹介」で紹介しているPHP Clientを使用しています。シンプルな例を紹介しましたが、マルチブロックを使用しているとJSONデータを深くたどっていく必要があるため少々手間がかかります。

最近の記事

カテゴリ

アーカイブ

スタッフ別