Skip to content

WordPress Compatibility ​

Introduction ​

A site moves from WordPress to kitloom by pointing kitloom at its database. Nothing is converted: kitloom reads the tables, options and meta as WordPress and its plugins left them, and the site keeps its content, its addresses and its settings.

The move is one way. kitloom writes new arrays as JSON (see Data), so WordPress is not expected to read the database back. How to rehearse it on a copy and compare the two sites page by page: Migrate from WordPress.

What is picked up ​

WordPress itself ​

WhatWhere WordPress keeps itkitloom
Posts, pages, attachments, revisionsposts, postmetakitloom/wp-schema
Categories, tags, custom taxonomiesterms, term_taxonomy, term_relationships, termmetakitloom/wp-schema
Commentscomments, commentmetakitloom/wp-schema
Users, their passwordsusers (WordPress's password hashes), usermetakitloom/wp-schema (the wordpress user provider and hash driver)
Rolesusermeta ({prefix}capabilities, {prefix}user_level), the {prefix}user_roles optionkitloom/permissions — who holds which role is shared with WordPress
Sign-upusers_can_register, default_rolekitloom/wp-schema, kitloom/permissions
Addressespermalink_structure, category_base, tag_base, show_on_front, page_on_front, page_for_postskitloom/site
Site settingsblogname, blogdescription, date_format, posts_per_page, sticky_posts…kitloom/settings, kitloom/site
Page templates_wp_page_template metakitloom/site
Blocksblock comments in post_content; synced patterns as wp_block postskitloom/site; dynamic blocks (latest posts, latest comments, archives, calendar, categories, search, tag cloud, page list) by kitloom/widgets
Menusnav_menu terms, nav_menu_item posts with _menu_item_* meta, locations in theme_mods_{stylesheet}kitloom/navigation
Widgetssidebars_widgets, widget_{type} optionskitloom/wp-schema (zones and layout), kitloom/widgets (WordPress's standard widgets)
Mediaattachment posts, _wp_attached_file, _wp_attachment_metadata, _thumbnail_id; files under /wp-content/uploads/Y/m/kitloom/media
Media shortcodes[gallery], [caption], [audio], [video], [playlist], [embed] in contentkitloom/media

Plugins ​

PluginWhat is keptkitloom
Rank Math SEOrank-math-options-titles, -general, -sitemap, -instant-indexing options; rank_math_title, rank_math_description, rank_math_robots, rank_math_canonical_url, rank_math_primary_category… meta; template variables (%title% %sep% %sitename%)kitloom/seo, kitloom/site
Rank Math Redirections, 404 Monitorrank_math_redirections, rank_math_redirections_cache, rank_math_404_logs tables; their keys in rank-math-options-generalkitloom/redirects
Yoast SEO (imported once)_yoast_wpseo_* post meta, the wpseo_taxonomy_meta option, wpseo_* user meta; wpseo, wpseo_titles, wpseo_social options — read once and written as Rank Math's keys abovekitloom/seo
Redirection (imported once)redirection_items, redirection_groups tables and redirection_options — read once and written as Rank Math's redirectionskitloom/redirects
Yoast SEO Premium's redirects (imported once)the wpseo-premium-redirects-base option (before Premium 3.1 wpseo-premium-redirects and wpseo-premium-redirects-regex) — read once and written as Rank Math's redirectionskitloom/redirects
Rank Math Link Counterrank_math_internal_links, rank_math_internal_meta tableskitloom/internal-links
ACF, Secure Custom Fieldsfield groups and fields as acf-field-group / acf-field posts; values under the field's meta key with the _{name} reference; options as options_{name}kitloom/custom-fields
ACF post types and taxonomiesacf-post-type, acf-taxonomy postskitloom/post-types
Contact Form 7wpcf7_contact_form posts and their _form, _mail, _mail_2, _messages, _additional_settings meta; [contact-form-7] shortcodeskitloom/forms
Flamingomessages as flamingo_inbound posts, the form they came from as a flamingo_inbound_channel termkitloom/forms
WooCommerceproduct posts, product_cat, product_tag, product_type, product_visibility; _price, _sku, _stock… meta; orders in the HPOS tables (wc_orders, wc_orders_meta, wc_order_addresses, woocommerce_order_items…); woocommerce_* optionskitloom/shop
Slide Anythingsa_slider posts with sa_* meta; [slide-anything] shortcodeskitloom/slider
Nextend Social Loginlinked Google and GitHub accounts in its social_users table; [nextend_social_login] shortcodeskitloom/social-accounts

Some modules take a plugin's settings or records once, on request: the module's settings page shows an Import button when the plugin's data is there, and an artisan command does the same. The plugin's own options and tables are left as they are, and importing again adds nothing.

PluginsImportkitloom
Site Kit by Google, MonsterInsights, Plausible Analytics, Connect Matomo, Yandex Metricaphp artisan analytics:importkitloom/analytics
GTM4WP, Site Kit by Google (Tag Manager)php artisan tag-manager:importkitloom/tag-manager
Meta pixel for WordPress, TikTok, LinkedIn Insight Tag, PixelYourSitephp artisan ad-pixels:importkitloom/ad-pixels
Complianz, CookieYesphp artisan cookie-consent:importkitloom/cookie-consent (Complianz's [cmplz-manage-consent] keeps working)
Yoast SEO — its settings and the head meta of posts, terms and authorsphp artisan seo:import --from=yoastkitloom/seo, into Rank Math's keys; what is set here already stays
Redirection — its rules with their hitsphp artisan redirects:importkitloom/redirects; what cannot come over is listed with the reason
Yoast SEO Premium — its redirectsphp artisan redirects:import --from=yoastkitloom/redirects; a source with a rule of its own here keeps it

Other modules do the job of a plugin without taking its data: kitloom/header-footer (Insert Headers and Footers, WPCode — snippets are pasted again), kitloom/two-factor (Two Factor, Wordfence — users set up their second factor again).

Content can also come in as a file: kitloom/import-export reads and writes WXR, the format of WordPress's Tools → Import / Export.

A module for a plugin's data ​

When a module replaces a WordPress plugin, the plugin's data is the module's data model. The site moves over and the module works with what is there.

1. Find out how the plugin stores things ​

Install the plugin on a WordPress site, use every feature, and look at what it wrote: its tables (SHOW CREATE TABLE), its options (SELECT * FROM wp_options WHERE option_name LIKE 'plugin%'), the meta keys of the records it touched. Note the formats — serialized arrays, on/off or 1/0 flags, IDs as strings.

Save samples as fixtures in the module's tests/Fixtures/ — rows exactly as the plugin wrote them. kitloom/custom-fields keeps a snapshot of every field type as Secure Custom Fields stores it.

2. Keep its tables and keys ​

php
// The plugin's table, created only when the site never had the plugin.
if (! Schema::hasTable('rank_math_redirections')) {
    Schema::create('rank_math_redirections', function (Blueprint $table): void {
        $table->id();
        $table->text('sources');
        $table->text('url_to');
        $table->unsignedSmallInteger('header_code');
        // …the rest as the plugin creates them
    });
}

Use the plugin's option names and meta keys as they are. Name them once, in a class of the module — ContactForm7 in kitloom/forms, RankMath\Options in kitloom/seo — so the rest of the code speaks in plain names.

3. Read both formats, write JSON ​

php
use Kitloom\WpSchema\Support\StoredArray;

$sources = StoredArray::toArray($row->sources);          // serialized by the plugin or JSON by kitloom
$row->sources = StoredArray::encode($sources);           // JSON from now on

Options that are one array with many keys — Rank Math keeps whole screens in one option — are read and written key by key: change the keys your module owns and leave the others as they are.

4. Test against what the plugin wrote ​

php
#[Test]
public function sources_are_read_from_what_rank_math_saved(): void
{
    $saved = 'a:1:{i:0;a:3:{s:6:"ignore";s:4:"case";s:7:"pattern";s:8:"Old-Page";s:10:"comparison";s:5:"exact";}}';

    $this->assertEquals([new Source('Old-Page', Comparison::Exact, ignoreCase: true)], Sources::decode($saved));
}

Run the module on a copy of a real site's database before calling it done: the plugin's data has cases no fixture thought of.

What kitloom does not do ​

  • Run WordPress plugins or themes. PHP code written for WordPress does not run; a plugin's data is supported when a kitloom module for it exists, and a theme is rewritten as a kitloom theme.
  • Keep the database readable by WordPress. New arrays are JSON; WordPress would not understand them. Moving back is not supported.
  • Carry over what lived outside the database. Visitors' cookie choices and sessions stay behind. Uploaded files are copied by hand — the contents of wp-content/uploads/ into the media disk, keeping the Y/m folders; old links to /wp-content/uploads/… then get a 301 to the new address (kitloom/media).
  • Run the block editor. Blocks in content are drawn as WordPress draws them; the admins edit the HTML with a visual editor (TinyMCE), not with Gutenberg.
  • Copy the site for you. The data moves with the database — or as a WXR file with kitloom/import-export.

kitloom — modules and themes for Laravel.
Pricing · Services · License · Refunds · Privacy · Community · [email protected]