PHPackages                             korvir/wp-migrations - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [API Development](/categories/api)
4. /
5. korvir/wp-migrations

ActiveLibrary[API Development](/categories/api)

korvir/wp-migrations
====================

Simple migration runner for WordPress

1.1.1(1mo ago)117MITPHPPHP &gt;=7.4CI failing

Since Feb 5Pushed 1mo agoCompare

[ Source](https://github.com/Korvir/wp-migrations)[ Packagist](https://packagist.org/packages/korvir/wp-migrations)[ RSS](/packages/korvir-wp-migrations/feed)WikiDiscussions main Synced 1mo ago

READMEChangelog (3)Dependencies (2)Versions (19)Used By (0)

Simple WP Migrations
====================

[](#simple-wp-migrations)

Simple, explicit database migrations for WordPress via WP-CLI.

This package provides a minimal execution-based migration system inspired by Laravel, but designed specifically for WordPress and MySQL/MariaDB.

#### Install

[](#install)

```
composer require korvir/wp-migrations
```

#### Requirements

[](#requirements)

- PHP 7.4+
- WordPress 5.5+
- MySQL/MariaDB
- WP-CLI

---

Migrations
----------

[](#migrations)

### Commands

[](#commands)

```
wp migrations add
wp migrations migrate
wp migrations rollback
wp migrations status
wp migrations reset
wp migrations fresh
```

#### Available Commands

[](#available-commands)

CommandDescription`wp migrations add `Create a new migration file.`wp migrations migrate`Run all pending migrations.`wp migrations rollback`Roll back the last batch of database migrations.`wp migrations rollback --step=N`Roll back the last `N` migrations.`wp migrations status`Display the status of all migrations.`wp migrations reset`Roll back all database migrations.`wp migrations fresh`Drop all tables and re-run all migrations.### Commands Options

[](#commands-options)

OptionDescription`--pretend`Show which migrations would be executed without running them.`--only=`Run only migrations whose filenames contain the given comma-separated name fragments.`--except=`Run all migrations except those whose filenames contain the given comma-separated name fragments.`--step=`Limit the number of migrations to roll back. Used with `rollback`.> Filtering options (`--only`, `--except`) apply only to the current command execution
> and do not affect migration state or batches.

```
// Example:
wp migrations migrate --only=2021_01_01_000000_create_users_table
wp migrations migrate --except=2021_01_01_000000_create_users_table
wp migrations migrate --only=2021_01_01_000000_create_users_table,2021_01_01_000001_create_posts_table
```

#### Migration Pretend mode (dry-run)

[](#migration-pretend-mode-dry-run)

All migration commands support the `--pretend` flag. When enabled, migrations are **not executed**. Instead, the command will show what *would* be done.

Preview pending migrations:

```
wp migrations migrate --pretend
wp migrations rollback --step=2 --pretend
```

### Migration Structure

[](#migration-structure)

```
return new class {
    public function up(){
        // apply changes
    }
    public function down(){
        // rollback changes
    }
};
```

---

Schema Builder &amp; Blueprint
------------------------------

[](#schema-builder--blueprint)

Schema and Blueprint provide a declarative API for describing structural tables in WordPress (MySQL/MariaDB) migrations.

### Methods:

[](#methods)

```
Schema::create();
Schema::table();
Schema::rename();
Schema::drop();
Schema::dropIfExists();
Schema::hasTable();
Schema::hasColumn();
Schema::hasIndex();
Schema::createView();
Schema::dropView();
```

#### Charset &amp; Collation

[](#charset--collation)

In `Schema::table()`, `charset()` and `collation()` change the table default charset and collation only.

Existing columns and data are not modified.

```
Schema::create('posts', function (Blueprint $table) {
    $table->charset('utf8mb4');
    $table->collation('utf8mb4_unicode_ci');
});

// If not specified, WordPress defaults ($wpdb->get_charset_collate()) are used.
```

### Table Columns

[](#table-columns)

#### Supported column types

[](#supported-column-types)

Blueprint methodSQL type`id()``BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY``increments()``INT UNSIGNED AUTO_INCREMENT``bigIncrements()``BIGINT UNSIGNED AUTO_INCREMENT``integer()``INT``bigInteger()``BIGINT``mediumInteger()``MEDIUMINT``smallInteger()``SMALLINT``tinyInteger()``TINYINT``boolean()``TINYINT(1)``string($length = 255)``VARCHAR($length)``char($length)``CHAR($length)``text()``TEXT``mediumText()``MEDIUMTEXT``longText()``LONGTEXT``binary()``BLOB``float()``FLOAT``double()``DOUBLE``decimal($precision, $scale)``DECIMAL(p, s)``date()``DATE``dateTime()``DATETIME``time()``TIME``timestamp()``TIMESTAMP``timestamps()``created_at` + `updated_at` (`DATETIME`)`year()``YEAR``json()``JSON``enum(array $values)``ENUM(...)``uuid()``CHAR(36)``ulid()``CHAR(26)``ipAddress()``VARCHAR(45)``macAddress()``VARCHAR(17)`#### Supported column Modifiers

[](#supported-column-modifiers)

Modifiers can be chained on column definitions.

ModifierDescription`nullable()`Allows `NULL``notNullable()`Sets `NOT NULL``default($value)`Default value`unsigned()`UNSIGNED (numeric types)`autoIncrement()`AUTO\_INCREMENT`comment($text)`Column comment`charset($charset)`Column charset`collation($collation)`Column collation`first()`Place column first`after($column)`Place column after another```
// Example:
$table->string('status', 20)
	->unsigned()
	->default(1)
	->comment('User status');
```

#### Changing column types

[](#changing-column-types)

```
// To modify an existing column, define it again and call change().
$table->string('email', 320)->change();
```

#### Dropping &amp; Renaming Columns

[](#dropping--renaming-columns)

```
$table->dropColumn('legacy');
$table->dropColumn(['foo', 'bar']);

$table->renameColumn('old_name', 'new_name');
```

#### Adding &amp; Dropping Indexes

[](#adding--dropping-indexes)

Primary keys are unnamed.

Unique and non-unique indexes may be named explicitly. If an index name is not provided, MySQL will generate one automatically.

To drop an index, you must know its name.

```
// Creating indexes
$table->primary('id');
$table->unique('email');
$table->index(['user_id', 'status']);

// Named indexes
$table->unique('email', 'unique_email');
$table->index(['user_id'], 'idx_user');

// Dropping indexes
$table->dropPrimary();
$table->dropIndex('idx_user');
$table->dropUnique('unique_email');
```

#### Adding &amp; Dropping Foreign Keys

[](#adding--dropping-foreign-keys)

This package does **not** attempt to:

- detect existing constraints
- infer relationships
- automatically manage rollback safety

Foreign keys are executed exactly as declared. If no constraint name is provided, the following naming convention is used: `{table}_{column}_foreign` === `(orders_user_id_foreign)`

```
// Examples:
Schema::table('orders', function (Blueprint $table) {
    $table->foreign('user_id')
        ->references('id')
        ->on('users')
        ->onDelete('cascade');
});

Schema::table('orders', function (Blueprint $table) {
    $table->dropForeign('orders_user_id_foreign');
});
```

This generates:

```
ALTER TABLE wp_orders
ADD CONSTRAINT orders_user_id_foreign
FOREIGN KEY (user_id)
REFERENCES wp_users(id)
ON DELETE CASCADE;

ALTER TABLE wp_orders DROP FOREIGN KEY orders_user_id_foreign;
```

#### Foreign Keys and Column Changes

[](#foreign-keys-and-column-changes)

MySQL does not allow modifying or dropping a column while a foreign key constraint exists.

When changing or dropping such columns, foreign keys must be dropped manually and re-created if necessary.

Examples:

```
// Changing a column type
public function up() {
    Schema::table('orders', function (Blueprint $table) {
        $table->dropForeign('fk_orders_user');
        $table->bigInteger('user_id')->change();
        $table->foreign('user_id')
            ->references('id')
            ->on('users');
    });
}

// Dropping a column that participates in a foreign key constraint
// requires dropping the foreign key first.
public function up() {
    Schema::table('orders', function (Blueprint $table) {
        $table->dropForeign('fk_orders_user');
        $table->dropColumn('user_id');
    });
}
```

---

#### Database Views

[](#database-views)

Views may be created using raw SQL.

```
Schema::createView('active_users', '
    SELECT id, email
    FROM users
    WHERE active = 1
');

Schema::dropView('active_users');
```

---

#### Raw SQL

[](#raw-sql)

You may execute arbitrary SQL queries using `Schema::raw()`.

```
// Single query
Schema::raw('ALTER TABLE users ENGINE=InnoDB');

// Multiple queries may be executed at once:
Schema::raw([
    'SET FOREIGN_KEY_CHECKS=0',
    'DROP TABLE legacy',
    'SET FOREIGN_KEY_CHECKS=1',
]);
```

---

### Migration stubs

[](#migration-stubs)

Migration stubs are selected automatically based on migration name prefix:

- create\_\* → create stub
- update\_\* → update stub
- rename\_\* → rename stub
- drop\_\* → drop stub

If no keyword is detected, the default stub is used.

### Stub publishing

[](#stub-publishing)

You need do define the `WP_MIGRATIONS_STUBS_PATH` constant. To customize migration templates, you can publish the default stubs:

```
wp migrations stub:publish
```

This will copy stub files into your project, where they can be freely modified.

---

---

---

Multisite
---------

[](#multisite)

Not supported.

But you may apply schema changes across multiple sites manually (e.g. by iterating over `get_sites()` and using `switch_to_blog()`).

In this case, the migration is still considered a single unit. Rollback correctness is the responsibility of the migration author.

Example:

```
public function up() {
    foreach (get_sites() as $site) {
        switch_to_blog($site->blog_id);

        Schema::table('orders', function (Blueprint $table) {
            $table->string('foo');
        });

        restore_current_blog();
    }
}
```

---

###  Health Score

39

—

LowBetter than 86% of packages

Maintenance89

Actively maintained with recent releases

Popularity9

Limited adoption so far

Community6

Small or concentrated contributor base

Maturity43

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~3 days

Recently: every ~10 days

Total

14

Last Release

59d ago

Major Versions

0.2.5 → 1.0.02026-02-07

### Community

Maintainers

![](https://www.gravatar.com/avatar/80a15cc47afd4c0f29e236e307b8b93f027c0bf990271a534c188a9a26ae5e6e?d=identicon)[korvir](/maintainers/korvir)

---

Top Contributors

[![Korvir](https://avatars.githubusercontent.com/u/6126662?v=4)](https://github.com/Korvir "Korvir (3 commits)")

### Embed Badge

![Health badge](/badges/korvir-wp-migrations/health.svg)

```
[![Health](https://phpackages.com/badges/korvir-wp-migrations/health.svg)](https://phpackages.com/packages/korvir-wp-migrations)
```

###  Alternatives

[stripe/stripe-php

Stripe PHP Library

4.0k143.3M480](/packages/stripe-stripe-php)[twilio/sdk

A PHP wrapper for Twilio's API

1.6k92.9M272](/packages/twilio-sdk)[facebook/php-business-sdk

PHP SDK for Facebook Business

90821.9M34](/packages/facebook-php-business-sdk)[meilisearch/meilisearch-php

PHP wrapper for the Meilisearch API

74513.7M114](/packages/meilisearch-meilisearch-php)[google/gax

Google API Core for PHP

265103.1M454](/packages/google-gax)[google/common-protos

Google API Common Protos for PHP

173103.7M50](/packages/google-common-protos)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
