Migrations
Introduction
The schema builder has no runner of its own. wp-kit supplies the missing half: a Migration base class and a helper that runs a list of them.
Writing a migration
Migrations live in backend/db/Migrations, one class per table or alteration, extending Migration and implementing up() and down():
use YourPlugin\Config;
use YourPlugin\Deps\BitApps\WPDatabase\Blueprint;
use YourPlugin\Deps\BitApps\WPDatabase\Connection;
use YourPlugin\Deps\BitApps\WPDatabase\Schema;
use YourPlugin\Deps\BitApps\WPKit\Migration\Migration;
if (!defined('ABSPATH')) {
exit;
}
final class YourPluginTagsTableMigration extends Migration
{
public function up(): void
{
Schema::withPrefix(Connection::wpPrefix() . Config::VAR_PREFIX)->create(
'tags',
function (Blueprint $table): void {
$table->id();
$table->string('title');
$table->string('slug');
$table->string('filter')->nullable();
$table->boolean('status')->defaultValue(1);
$table->timestamps();
}
);
}
public function down(): void
{
Schema::withPrefix(Connection::wpPrefix() . Config::VAR_PREFIX)->drop('tags');
}
}
Schema::withPrefix(Connection::wpPrefix() . Config::VAR_PREFIX) resolves the same physical table your models target — the schema builder applies no prefix on its own.
Running migrations
MigrationHelper takes the list of migration classes:
use YourPlugin\Deps\BitApps\WPKit\Migration\MigrationHelper;
MigrationHelper::migrate(InstallerProvider::migration()); // runs up()
MigrationHelper::drop(InstallerProvider::migration()); // runs down()
The plugin calls migrate() on activation and on version change, and drop() on uninstall. InstallerProvider owns that list, so a new migration is registered by adding its class there.
Altering an existing table
Never edit a migration that has already shipped — sites that ran it will not run it again. Add a new one:
final class YourPluginTagsAddColorMigration extends Migration
{
public function up(): void
{
Schema::withPrefix(Connection::wpPrefix() . Config::VAR_PREFIX)->edit(
'tags',
function (Blueprint $table): void {
$table->string('color')->nullable();
}
);
}
public function down(): void
{
Schema::withPrefix(Connection::wpPrefix() . Config::VAR_PREFIX)->edit(
'tags',
function (Blueprint $table): void {
$table->dropColumn('color');
}
);
}
}
There is no migrations table and no per-migration ledger. migrate() runs every registered migration every time it is called, so each up() must be safe to re-run — Schema::create() emits CREATE TABLE IF NOT EXISTS, but an edit() adding a column will fail on the second run unless you check first.