PHPackages                             georgeff/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. [Database &amp; ORM](/categories/database)
4. /
5. georgeff/schema

ActiveLibrary[Database &amp; ORM](/categories/database)

georgeff/schema
===============

Database schema builder — driver-agnostic blueprints compiled to SQL for MySQL, PostgreSQL, and SQLite

1.2.0(1mo ago)0681MITPHPPHP ^8.4CI passing

Since Jun 12Pushed 1mo agoCompare

[ Source](https://github.com/MikeGeorgeff/schema)[ Packagist](https://packagist.org/packages/georgeff/schema)[ RSS](/packages/georgeff-schema/feed)WikiDiscussions main Synced 1w ago

READMEChangelogDependencies (6)Versions (4)Used By (1)

georgeff/schema
===============

[](#georgeffschema)

Database schema builder for PHP. Define table structures using a fluent blueprint API and compile them to SQL for MySQL, PostgreSQL, or SQLite. Produces raw SQL strings — no connection required.

Installation
------------

[](#installation)

```
composer require georgeff/schema
```

Overview
--------

[](#overview)

`georgeff/schema` separates schema definition from execution. You build a `Blueprint`, pass it to a compiler, and receive an array of SQL strings to run however you like.

```
use Georgeff\Schema\Blueprint;
use Georgeff\Schema\Compiler\PostgreSQLCompiler;

$blueprint = new Blueprint('users');
$blueprint->id();
$blueprint->string('email')->unique();
$blueprint->string('name');
$blueprint->timestamps();

$compiler = new PostgreSQLCompiler();

foreach ($compiler->create($blueprint) as $sql) {
    // execute $sql against your connection
}
```

Compilers
---------

[](#compilers)

Three compilers are available, each implementing `CompilerInterface`:

```
use Georgeff\Schema\Compiler\MySQLCompiler;
use Georgeff\Schema\Compiler\PostgreSQLCompiler;
use Georgeff\Schema\Compiler\SQLiteCompiler;
```

Both `MySQLCompiler` and `PostgreSQLCompiler` accept optional constructor arguments:

```
$compiler = new MySQLCompiler(
    engine:  'InnoDB',            // default
    charset: 'utf8mb4',           // default
    collate: 'utf8mb4_unicode_ci' // default
);

$compiler = new PostgreSQLCompiler(
    schema: 'public' // default; set to your target schema if not using the default
);
```

Compiler Methods
----------------

[](#compiler-methods)

### `create(Blueprint $blueprint): string[]`

[](#createblueprint-blueprint-string)

Returns one or more SQL statements to create the table. MySQL always returns a single statement with indexes inline. PostgreSQL and SQLite return additional `CREATE INDEX` statements when non-primary indexes are present.

```
$statements = $compiler->create($blueprint);
// ['CREATE TABLE ...', 'CREATE UNIQUE INDEX ...']
```

### `drop(string $table, bool $ifExists = false): string`

[](#dropstring-table-bool-ifexists--false-string)

```
$compiler->drop('users');
// DROP TABLE "users";

$compiler->drop('users', ifExists: true);
// DROP TABLE IF EXISTS "users";
```

### `tableExists(): string`

[](#tableexists-string)

Returns a parameterized SQL query that checks whether a table exists. Pass the table name as a bound parameter when executing — do not interpolate it directly.

```
$sql = $compiler->tableExists();
// execute with [$tableName] as bindings; returns a count
```

The query shape varies by driver:

- **MySQL:** queries `information_schema.tables` scoped to `DATABASE()`
- **PostgreSQL:** queries `information_schema.tables` scoped to the configured schema (default `public`)
- **SQLite:** queries `sqlite_master`

### `alter(Blueprint $blueprint): string[]`

[](#alterblueprint-blueprint-string)

Returns one statement per change. Used for adding/dropping columns, indexes, and foreign keys on an existing table.

```
$blueprint = new Blueprint('users');
$blueprint->string('phone')->nullable();
$blueprint->dropColumn('bio');

foreach ($compiler->alter($blueprint) as $sql) {
    // execute $sql
}
```

> **SQLite limitation:** SQLite only supports `ADD COLUMN` and `DROP COLUMN`. Calls to `dropIndex()`, `dropForeign()`, and `foreign()` on a Blueprint passed to `SQLiteCompiler::alter()` are silently ignored.

Blueprint
---------

[](#blueprint)

### Column Types

[](#column-types)

MethodDescription`id(string $name = 'id')``BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY``bigInteger(string $name)`8-byte integer`integer(string $name)`4-byte integer`smallInteger(string $name)`2-byte integer`tinyInteger(string $name)`1-byte integer (MySQL) / `SMALLINT` (PostgreSQL)`float(string $name)`Floating point`decimal(string $name, int $precision = 8, int $scale = 2)`Fixed precision`string(string $name, int $length = 255)``VARCHAR``char(string $name, int $length = 1)`Fixed-length string`text(string $name)`Unbounded text`boolean(string $name)`Boolean (`TINYINT(1)` on MySQL, `BOOLEAN` on PostgreSQL, `INTEGER` on SQLite)`json(string $name)`JSON (`TEXT` on SQLite)`uuid(string $name)`UUID (`CHAR(36)` on MySQL, `UUID` on PostgreSQL, `TEXT` on SQLite)`date(string $name)`Date`time(string $name)`Time`timestamp(string $name)`Timestamp (`TEXT` on SQLite)`timestamps()`Adds nullable `created_at` and `updated_at` timestamp columns### Column Modifiers

[](#column-modifiers)

Modifiers chain off any column factory method:

```
$blueprint->string('email')
    ->nullable()
    ->default('guest@example.com')
    ->unique();
```

`defaultRaw()` emits the provided string directly into the DDL without quoting — use it for SQL functions and expressions:

```
$blueprint->timestamp('created_at')->defaultRaw('CURRENT_TIMESTAMP');
$blueprint->string('id')->defaultRaw('gen_random_uuid()');
```

> **Warning:** `defaultRaw()` must never be called with user-supplied input. It is intended for developer-authored migration files only.

ModifierDescription`nullable(bool $value = true)`Allows `NULL`; pass `false` to revert`unsigned()``UNSIGNED` (MySQL only; ignored on PostgreSQL and SQLite)`default(mixed $value)`Sets a default value`defaultRaw(string $sql)`Sets a raw SQL expression as the default — emitted unquoted`incrementing()``AUTO_INCREMENT` (MySQL) / `SERIAL`/`BIGSERIAL` (PostgreSQL) / `AUTOINCREMENT` (SQLite)`primary(?string $name = null)`Marks column as primary key`unique(?string $name = null)`Adds a unique index`index(?string $name = null)`Adds a regular index### Foreign Keys

[](#foreign-keys)

```
$blueprint->bigInteger('user_id');
$blueprint->foreign('user_id')
    ->references('id')
    ->on('users')
    ->onDelete('CASCADE')
    ->onUpdate('RESTRICT');
```

An optional constraint name can be passed as the second argument to `foreign()`:

```
$blueprint->foreign('user_id', 'fk_posts_user_id')
    ->references('id')
    ->on('users');
```

Valid actions for `onDelete` and `onUpdate`: `NO ACTION`, `RESTRICT`, `SET NULL`, `CASCADE`. Both default to `RESTRICT`.

### ALTER Operations

[](#alter-operations)

```
$blueprint = new Blueprint('users');

// Add columns
$blueprint->string('phone')->nullable();

// Drop columns
$blueprint->dropColumn('legacy_field');

// Drop indexes
$blueprint->dropIndex('users_email_unique');

// Drop foreign keys
$blueprint->dropForeign('posts_user_id_foreign');
```

Index Naming
------------

[](#index-naming)

When no name is provided, indexes are auto-named using the pattern:

```
{table}_{column}_{suffix}

```

Where suffix is `primary`, `unique`, `index`, or `foreign`. For example:

```
$blueprint->string('email')->unique();
// Index name: users_email_unique

$blueprint->foreign('user_id')->references('id')->on('users');
// Constraint name: posts_user_id_foreign
```

Pass an explicit name to override:

```
$blueprint->string('email')->unique('my_email_constraint');
```

Driver Differences
------------------

[](#driver-differences)

FeatureMySQLPostgreSQLSQLiteQuotingBackticksDouble quotesDouble quotesAuto-increment`AUTO_INCREMENT``SERIAL` / `BIGSERIAL``INTEGER PRIMARY KEY AUTOINCREMENT`Unsigned columnsSupportedSilently ignoredSilently ignoredBoolean`TINYINT(1)``BOOLEAN``INTEGER`UUID`CHAR(36)``UUID``TEXT`Indexes in `CREATE TABLE`InlineSeparate statementsSeparate statements`ALTER` foreign key supportYesYesNo`tableExists` source`information_schema` + `DATABASE()``information_schema` + configured schema`sqlite_master`

###  Health Score

44

—

FairBetter than 90% of packages

Maintenance93

Actively maintained with recent releases

Popularity12

Limited adoption so far

Community8

Small or concentrated contributor base

Maturity53

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 ~5 days

Total

3

Last Release

35d ago

### Community

Maintainers

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

---

Top Contributors

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

###  Code Quality

TestsPHPUnit

Static AnalysisPHPStan

Code StylePHP\_CodeSniffer

Type Coverage Yes

### Embed Badge

![Health badge](/badges/georgeff-schema/health.svg)

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

###  Alternatives

[jdorn/sql-formatter

a PHP SQL highlighting library

3.9k117.2M118](/packages/jdorn-sql-formatter)[propel/propel1

Propel is an open-source Object-Relational Mapping (ORM) for PHP5.

8351.6M87](/packages/propel-propel1)[pgvector/pgvector

pgvector support for PHP

198741.5k13](/packages/pgvector-pgvector)

PHPackages © 2026

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