Usage
Core patterns and workflows for WPZylos Migrations.
Creating Migrations
Migrations extend the base Migration class and use $this->db (Connection) and helper methods.
Basic Migration
// database/migrations/2024_01_15_create_products_table.php
<?php
declare(strict_types=1);
namespace MyPlugin\Database\Migrations;
use WPZylos\Framework\Migrations\Migration;
class CreateProductsTable extends Migration
{
public function up(): void
{
$this->create('myplugin_products', [
'id' => 'bigint(20) unsigned NOT NULL AUTO_INCREMENT',
'name' => 'varchar(255) NOT NULL',
'description' => 'text DEFAULT NULL',
'price' => 'decimal(10,2) NOT NULL DEFAULT 0.00',
'stock' => 'int(11) NOT NULL DEFAULT 0',
'created_at' => 'datetime DEFAULT CURRENT_TIMESTAMP',
'updated_at' => 'datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP',
], [
'PRIMARY KEY (id)',
]);
}
public function down(): void
{
$this->drop('myplugin_products');
}
}
Note: The
create()helper uses WordPressdbDelta()internally. Table names are automatically prefixed with$wpdb->prefix.
Migration Helpers
The base Migration class provides these protected helper methods:
create()
$this->create('table_name', [
'column_name' => 'column_definition',
], [
'PRIMARY KEY (id)',
'KEY idx_status (status)',
]);
dropTable() / drop()
$this->dropTable('table_name');
// or alias:
$this->drop('table_name');
charsetCollate()
$charset = $this->charsetCollate();
// Returns e.g.: "DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci"
Raw SQL via Connection
public function up(): void
{
$prefix = $this->db->wpdb()->prefix;
$charset = $this->charsetCollate();
$this->runDbDelta("
CREATE TABLE `{$prefix}myplugin_orders` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`user_id` bigint(20) unsigned NOT NULL,
`total` decimal(10,2) NOT NULL DEFAULT 0.00,
`status` varchar(50) NOT NULL DEFAULT 'pending',
`created_at` datetime DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (id),
KEY idx_user (user_id),
KEY idx_status (status)
) {$charset};
");
}
Running Migrations
Via Container
$migrator = $app->make(Migrator::class);
// Run all pending migrations
$ran = $migrator->run();
// ['2024_01_15_create_products_table']
// Rollback last batch
$rolledBack = $migrator->rollback();
// Rollback last 2 batches
$rolledBack = $migrator->rollback(2);
// Get migration status
$status = $migrator->status();
// Get only pending migrations
$pending = $migrator->getPending();
Via WP-CLI
wp myplugin migrate # Run pending
wp myplugin migrate:rollback # Rollback last batch
wp myplugin migrate:status # Show status
Modifying Tables
Use raw SQL for table modifications:
class AddSkuToProducts extends Migration
{
public function up(): void
{
$prefix = $this->db->wpdb()->prefix;
$this->db->query(
"ALTER TABLE `{$prefix}myplugin_products` ADD COLUMN `sku` varchar(50) DEFAULT NULL AFTER `name`"
);
}
public function down(): void
{
$prefix = $this->db->wpdb()->prefix;
$this->db->query(
"ALTER TABLE `{$prefix}myplugin_products` DROP COLUMN `sku`"
);
}
}
Migration Naming
Use descriptive names with timestamps. Files are sorted alphabetically:
2024_01_15_000001_create_users_table.php
2024_01_15_000002_create_products_table.php
2024_01_16_000001_add_sku_to_products.php
2024_01_17_000001_create_orders_table.php
ServiceProvider Registration
$app->register(new \WPZylos\Framework\Migrations\MigrationsServiceProvider());
This registers:
MigrationRepository::class— Tracks migration stateMigrator::class— Migration runner
Dependencies
wpzylos-database— Required forConnectionwpzylos-core— Required forContextInterface