Data Migration

 How We Programmatically Escaped WordPress PostMeta

TL;DR: Migrating from WordPress requires more than moving data; it requires remodeling unstructured wp_postmeta into strict JSON blocks. We built a dedicated migration controller to handle this, including the complex logic of preserving "dirty" unsaved draft states. 

The PostMeta Swamp

Migrating off WordPress isn't a simple data dump. It is a fundamental remodeling of how your application thinks about data. WordPress crams everything that isn't a title or body into wp_postmeta, resulting in a chaotic, unindexed swamp of serialized PHP strings. When we built the migration tooling for StakCMS, we couldn't just import that mess. We had to map it to our strict ContentBlock architecture.

Programmatic Translation

We built BlogMigrationService specifically to handle this translation programmatically. It reads the raw HTML and meta-keys, and forces them into JSON schemas.

But the hardest part wasn't the text; it was the state. In headless systems, you usually have a Draft and a Published state. If a post was published in WP, then edited but not published again, we have to preserve that dirty state without destroying the live snapshot. 

// BlogMigrationService.php
if ($entry->last_published_at !== null) {
    $this->promotePost($post);
    // Mirroring "Modified" status:
    // If it was edited after being published, we revert the new post's
    // last_published_at so the UI knows it has unsaved drafts.
    if ($entry->updated_at->gt($entry->last_published_at->addSeconds(5)))
    { $post->update(['last_published_at' => $entry->last_published_at]);
    }
} 
Summary: We chose to handle the heavy logic directly in the migration controller rather than relying on a generic third-party ETL tool. This ensures the data arrives perfectly structured and state-accurate for a modern frontend.
Tags
WordPress migration
wp_postmeta
StakCMS migration tool
legacy CMS migration
JSON schemas
headless CMS data mapping
legacy CMS migration
Share