PHPackages                             wptechnix/wp-db-schema - 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. wptechnix/wp-db-schema

ActiveLibrary

wptechnix/wp-db-schema
======================

A strongly-typed schema definition and migration toolkit for WordPress custom database tables — a modern, safe alternative to dbDelta().

00PHPCI passing

Since Jul 30Pushed todayCompare

[ Source](https://github.com/WPTechnix/wp-db-schema)[ Packagist](https://packagist.org/packages/wptechnix/wp-db-schema)[ RSS](/packages/wptechnix-wp-db-schema/feed)WikiDiscussions main Synced today

READMEChangelogDependenciesVersions (1)Used By (0)

WP DB Schema
============

[](#wp-db-schema)

[![License](https://camo.githubusercontent.com/cbfb6a69657a9456e17a03dda43be99a118b839be368e9d04b5fcf7e93ab6cce/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f6c2f7770746563686e69782f77702d64622d736368656d61)](https://github.com/WPTechnix/wp-db-schema/blob/main/LICENSE)[![PHP Version](https://camo.githubusercontent.com/3dd038b8a8ebd57493c0dbfcb32aa479f1237ff4f9579d4f7ab09a0c77e228fe/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f7068702d762f7770746563686e69782f77702d64622d736368656d61)](https://packagist.org/packages/wptechnix/wp-db-schema)[![CI](https://github.com/WPTechnix/wp-db-schema/actions/workflows/ci.yml/badge.svg)](https://github.com/WPTechnix/wp-db-schema/actions/workflows/ci.yml)

Type-safe schema definitions and migrations for WordPress custom database tables.

```
class Customers_Table extends Table {

    protected string $name = 'customers';

    public function columns(): array {
        return [
            Column::id(),
            Column::string( 'email' ),
            Column::boolean( 'is_active' )->default( true ),
            ...Column::timestamps(),
        ];
    }

    public function indexes(): array {
        return [ Index::unique( 'email' ) ];
    }
}
```

Quick install
-------------

[](#quick-install)

```
composer require wptechnix/wp-db-schema
```

Requires PHP 8.0+ and MySQL 5.6+ / MariaDB 10.1+.

Quick start
-----------

[](#quick-start)

```
use WPTechnix\WP_DB_Schema\Exceptions\WP_DB_Schema_Exception;
use WPTechnix\WP_DB_Schema\Installation\Schema_Manager;

function my_plugin_schema(): Schema_Manager {
    return Schema_Manager::for_wpdb( 'myplugin_' )
        ->version( '1.0.0' )
        ->tables( [ Customers_Table::class ] );
}

register_activation_hook( __FILE__, static function (): void {
    try {
        my_plugin_schema()->migrate();
    } catch ( WP_DB_Schema_Exception $e ) {
        error_log( 'MyPlugin schema: ' . $e->getMessage() );
        wp_die( 'Failed to install database tables. Please contact support.' );
    }
} );
```

Why not dbDelta
---------------

[](#why-not-dbdelta)

`dbDelta()` is a parser — it reads your CREATE TABLE string, compares it with the live table, guesses at the differences, and issues its own ALTER statements.

`dbDelta()`wp-db-schemaInputA SQL string it parsesPHP objectsDrop a column or indexNever happens`drop_column()`, `drop_index()`Rename a columnNot possible`change_column()`Foreign keysNot supportedSupportedWhitespaceLoad-bearing, `PRIMARY KEY  (id)` mattersIrrelevantFailure modeAn array of strings, usually ignoredAn exceptionFresh install vs upgradeOne code path, guessedTwo paths, decidedThe two that cost people the most:

- **It never drops anything.** Removed columns accumulate in your users' tables forever.
- **Failures look like successes.** The return value is an array of human-readable strings that nobody checks.

The one core concept
--------------------

[](#the-one-core-concept)

This library has two kinds of classes. You write both, but only one kind runs on any given site.

A **table class** describes what a table should look like today. A **migration**describes one change between two versions. Every schema change means two edits.

SituationWhat runsFresh installThe table classes. No migrations.Existing site, older versionOnly the migrations between versions.Existing site, current versionNothing. Already up to date.```
class Add_Phone_To_Customers extends Abstract_Migration {

    protected string $version = '1.1.0';

    public function up( Schema $schema ): void {
        $schema->table( 'customers', function ( Table_Builder $table ): void {
            $table->add_column( Column::string( 'phone', 32 )->nullable() );
        } );
    }
}
```

A fresh install creates the table with `phone` already in it. An upgrade from 1.0.0 runs this one migration. Both end up identical.

This includes adding new tables. The library never scans for new table classes during an upgrade — only migrations run.

What you get
------------

[](#what-you-get)

- **Every column type as a method.** `Column::string()`, `Column::decimal()`, `Column::enum()`. The method name is the SQL type. Each returns a class that exposes only the modifiers that type allows.
- **Real foreign keys** with ON DELETE and ON UPDATE actions. Tables are created in two passes so registration order never matters.
- **Constraint names that survive.** Names use the blog ID, not the table prefix, so they stay valid when `$table_prefix` changes or a single-site becomes multisite.
- **Idempotent operations.** `add_column_if_not_exists()`, `drop_index_if_exists()`and similar for state you cannot be sure of.
- **Custom SQL with prefix resolution.** `$schema->statement( 'UPDATE {orders} SET status = %s', [ 'paid' ] )` — bound values, `{orders}` becomes the prefixed table name.
- **Exceptions always.** A single base class `WP_DB_Schema_Exception`. Nothing fails quietly.
- **Multisite** for both per-site and network-wide tables.
- **No WordPress dependency** below the connection layer. A PDO handle works for tests and CLI tooling.

Where to go next
----------------

[](#where-to-go-next)

If you are…Start hereNew to schema management[Getting Started](docs/getting-started/01-installation.md) — walk through everything step by stepExperienced[Quick Reference](docs/reference/quick-reference.md) — all methods and signatures on one pageSolving a specific problem[How-To Guides](docs/how-to/working-with-columns.md) — columns, indexes, foreign keys, migrationsCurious about design decisions[Explanation](docs/explanation/why-not-dbdelta.md) — why two paths, constraint naming, collationMoving from dbDelta[Migration Guide](docs/migration-guides/from-dbdelta.md)Looking for a specific API[Column API](docs/reference/column-api.md) · [Index &amp; FK API](docs/reference/index-and-foreign-key-api.md) · [Schema Manager API](docs/reference/schema-manager-api.md)Stuck[Glossary](docs/glossary.md)License
-------

[](#license)

MIT. See [LICENSE](LICENSE).

###  Health Score

20

—

LowBetter than 12% of packages

Maintenance65

Regular maintenance activity

Popularity0

Limited adoption so far

Community6

Small or concentrated contributor base

Maturity11

Early-stage or recently created project

 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.

### Community

Maintainers

![](https://www.gravatar.com/avatar/e0fb168547a02b4a7b28df9403ab375f354591c75e814dce020f245e77f04e5f?d=identicon)[owaisahmed5300](/maintainers/owaisahmed5300)

---

Top Contributors

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

### Embed Badge

![Health badge](/badges/wptechnix-wp-db-schema/health.svg)

```
[![Health](https://phpackages.com/badges/wptechnix-wp-db-schema/health.svg)](https://phpackages.com/packages/wptechnix-wp-db-schema)
```

PHPackages © 2026

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