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 forwarddown()
- 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');
}
};