Skip to main content

Schema Builder

The Schema Builder provides a fluent API for defining table structures in a database-agnostic way.

Snippet context

Snippets show only the Schema Builder calls. Driver selection and migration execution are covered in the migrations guides.

Creating Tables

Use schema.create() to define a new table:

class CreateTableExample extends Migration {
const CreateTableExample();


void up(SchemaBuilder schema) {
schema.create('users', (table) {
table.increments('id');
table.string('email').unique();
table.string('name').nullable();
table.boolean('active').defaultValue(true);
table.timestamps();
});
}


void down(SchemaBuilder schema) {
schema.drop('users');
}
}
Table prefixing

If DataSourceOptions.tablePrefix is set, schema operations automatically prefix unqualified table names (create/alter/drop/rename). Schema‑qualified names (e.g., public.users) are not prefixed.

Column Types

void primaryKeyExamples(TableBuilder table) {
table.id(); // bigIncrements('id')
table.increments('id'); // Auto-incrementing integer
table.bigIncrements('id'); // Auto-incrementing bigint
table.uuid('id'); // UUID column
table.ulid('id'); // ULID column
}

Column Modifiers

Chain modifiers to customize column behavior:

void modifierExamples(TableBuilder table) {
table
.string('email')
.nullable() // Allow NULL
.unique() // Unique constraint
.defaultValue('default@example.com');

table.integer('id').primaryKey().autoIncrement().unsigned();

table
.timestamp('created_at')
.useCurrentTimestamp() // DEFAULT CURRENT_TIMESTAMP
.useCurrentOnUpdate(); // ON UPDATE CURRENT_TIMESTAMP

table.string('slug').comment('URL-friendly identifier');
}

Timestamps & Soft Deletes

void timestampExamples(TableBuilder table) {
// Add created_at and updated_at
table.timestamps(); // Non-timezone aware
table.timestampsTz(); // Timezone aware (UTC)
table.nullableTimestamps(); // Nullable, no defaults
table.nullableTimestampsTz(); // Nullable, timezone aware

// Add soft delete column
table.softDeletes(); // Non-timezone aware
table.softDeletesTz(); // Timezone aware (UTC)
}

Indexes

void indexExamples(TableBuilder table) {
// Simple index
table.index(['email']);

// Composite index
table.index(['user_id', 'created_at']);

// Unique index
table.unique(['slug']);

// Full-text search
table.fullText(['title', 'body']);

// Spatial index
table.spatialIndex(['location']);

// Named index
table.index(['email']).name('idx_users_email');
}

Foreign Keys

Reference Actions

  • ReferenceAction.cascade - Delete/update child rows
  • ReferenceAction.restrict - Prevent if children exist
  • ReferenceAction.setNull - Set foreign key to NULL
  • ReferenceAction.noAction - No action (check deferred)

Altering Tables

Use schema.table() to modify existing tables:

    schema.table('users', (table) {
// Add columns
table.string('avatar_url').nullable();

// Drop columns
table.dropColumn('old_field');

// Rename columns
table.renameColumn('email', 'primary_email');

// Add indexes
table.index(['avatar_url']);

// Drop indexes
table.dropIndex('idx_old_index');
});

Dropping Tables

void dropRenameExamples(SchemaBuilder schema) {
schema.drop('users');
schema.drop('users', ifExists: true);
schema.dropIfExists('users');
schema.rename('old_name', 'new_name');
}

Driver-Specific Overrides

Customize schema for different databases:

Use this to conditionally apply types or modifiers that vary by database.