GitHub

Creating Migrations

Generate a new migration file using the Spark CLI:

php spark make:migration users

// Create a pivot migration table
php spark make:migration --pivot

// Create a migration with a seeder
php spark make:migration users -s

// Create a seeder for the users table
php spark make:seeder users

This creates a new file in database/migrations/ with timestamp prefix:

<?php

use Spark\Database\Schema\Blueprint;
use Spark\Database\Schema\Schema;

return new class {
    public function up(): void
    {
        Schema::create('users', function (Blueprint $table) {
            $table->id();
            $table->string('name');
            $table->string('email')->unique()->required();
            $table->string('password')->required();
            $table->timestamps();
        });
    }

    public function down(): void
    {
        Schema::dropIfExists('users');
    }
};

Running Migrations

# Run all pending migrations
php spark migrate:run

// migrate all pending migrations and seeders
php spark migrate:run -s

# Rollback the last migration
php spark migrate:rollback

# Rollback multiple migrations
php spark migrate:rollback 2

# Reset and re-run all migrations
php spark migrate:fresh

# Reset and re-run all migrations and seeders
php spark migrate:fresh -s

Schema Builder

Column Types

$table->id(); // Auto-incrementing ID
$table->string('name', 100); // String with optional length
$table->text('description'); // Long text
$table->integer('votes'); // Integer
$table->boolean('active'); // Boolean
$table->decimal('amount', 8, 2); // Decimal with precision
$table->date('created_at'); // Date only
$table->dateTime('updated_at'); // Date and time
$table->timestamp('published_at'); // Timestamp
$table->enum('status', ['active', 'pending']); // Enumeration

Column Modifiers

$table->string('email')->unique(); // Unique constraint
$table->string('name')->nullable(); // Allows NULL values
$table->integer('count')->default(0); // Default value
$table->string('ip')->required(); // NOT NULL constraint
$table->integer('views')->unsigned(); // Unsigned integer

Indexes

// Single column index
$table->string('email')->unique();

// Composite index
$table->index(['account_id', 'created_at']);

// Primary key
$table->primary(['id', 'parent_id']);

Foreign Keys

// Simple foreign key
$table->foreignId('user_id')->constrained();

// Custom foreign key
$table->foreign('author_id')->references('id')->on('authors');

// With actions
$table->foreign('user_id')
    ->references('id')
    ->on('users')
    ->onDelete('cascade');

Modifying Tables

Schema::table('users', function (Blueprint $table) {
    $table->string('new_column')->nullable();
    $table->dropColumn('old_column');
    $table->dropIndex(['email', 'status']);
    $table->dropForeign('user_id', 'users');
});

Migration Structure

Each migration class contains two methods:

  • up() - Runs when migrating forward
  • down() - Runs when rolling back

Best Practices

  • Keep migrations focused on one schema change
  • Always implement the down() method
  • Use descriptive migration names
  • Test migrations in development before production
  • Consider data migrations for large changes

Full Example

<?php

use Spark\Database\Schema\Blueprint;
use Spark\Database\Schema\Schema;

return new class {
    public function up(): void
    {
        Schema::create('posts', function (Blueprint $table) {
            $table->id();
            $table->foreignId('user_id')
                ->constrained('users')
                ->cascadeOnDelete();
            $table->string('title');
            $table->string('slug')->unique();
            $table->text('content');
            $table->boolean('published')->default(false);
            $table->timestamp('published_at')->nullable();
            $table->timestamps();
            
            $table->index(['title', 'published_at']);
        });

        Schema::create('comments', function (Blueprint $table) {
            $table->id();
            $table->foreignId('post_id')->constrained('posts');
            $table->foreignId('user_id')->constrained('users');
            $table->text('body');
            $table->timestamps();
        });
    }

    public function down(): void
    {
        Schema::dropIfExists('comments');
        Schema::dropIfExists('posts');
    }
};