About laravel-migrations
A reference skill for Laravel 13 database migrations, for developers managing schema changes and data setup. It covers Schema Builder operations, constraints, Artisan commands, seeders, migration testing, and production rollout, including pgvector extension setup.
Key features
- 01Schema Builder table and column changes
- 02Indexes and foreign key constraints
- 03Artisan migration commands
- 04Seeders and migration testing
- 05Production rollout and troubleshooting
- 06pgvector extension setup
Use cases
- 01Creating or changing database tables
- 02Adding indexes and cascading foreign keys
- 03Seeding data and testing rollbacks
- 04Enabling pgvector in migrations
Install
Copy the command and run it in a terminal.
npx skills add https:/ / github.com/ fusengine/ claude-plugins --skill laravel-migrationsAfter installing, type/laravel-migrationsin Claude Code to confirm it loaded.
Details
From the project READMELaravel Migrations
Agent Workflow (MANDATORY)
Before ANY implementation, spawn 3 agents in parallel, one Agent call each with a name:
- fuse-ai-pilot:explore-codebase - Check existing migrations
- fuse-ai-pilot:research-expert - Verify Laravel 13 patterns via Context7
- mcp__context7__query-docs - Check specific Schema Builder features
After implementation, run fuse-ai-pilot:sniper for validation.
Overview
| Feature | Description |
|---|---|
| Schema Builder | Create, modify, drop tables |
| Columns | 50+ column types with modifiers |
| Indexes | Primary, unique, fulltext, spatial |
| Foreign Keys | Constraints with cascade options |
| Seeders | Populate tables with data |
Critical Rules
- Always define down() - Reversible migrations
- Use foreignId()->constrained() - Not raw unsignedBigInteger
- Add indexes on foreign keys - Performance critical
- Test rollback before deploy - Validate down() works
- Never modify deployed migrations - Create new ones
Decision Guide
Migration Type
Need schema change?
├── New table → make:migration create_X_table
├── Add column → make:migration add_X_to_Y_table
├── Modify column → make:migration modify_X_in_Y_table
├── Add index → make:migration add_index_to_Y_table
└── Seed data → make:seeder XSeeder
Column Type Selection
| Use Case | Type | Example |
|---|---|---|
| Primary Key | id() | Auto-increment BIGINT |
| Foreign Key | foreignId()->constrained() | References parent |
| UUID Primary | uuid()->primary() | UUIDs |
| Boolean | boolean() | is_active |
| Enum | enum('status', [...]) | order_status |
| JSON | json() | preferences |
| Money | decimal('price', 10, 2) | 99999999.99 |
| Timestamps | timestamps() | created_at, updated_at |
| Soft Delete | softDeletes() | deleted_at |
Foreign Key Cascade
| Scenario | onDelete | Use Case |
|---|---|---|
| Strict integrity | restrictOnDelete() | Financial records |
| Auto-cleanup | cascadeOnDelete() | Post → Comments |
| Preserve with null | nullOnDelete() | Optional relations |
| No action | noActionOnDelete() | Audit logs |
Reference Guide
Core Concepts
| Topic | Reference | When to Consult |
|---|---|---|
| Schema | schema.md | Table operations |
| Columns | columns.md | Column types |
| Indexes | indexes.md | Performance indexes |
| Foreign Keys | foreign-keys.md | Constraints |
| Commands | commands.md | Artisan commands |
| Seeding | seeding.md | Populate data |
Advanced Topics
| Topic | Reference | When to Consult |
|---|---|---|
| Testing | testing.md | Test migrations |
| Production | production.md | Deploy safely |
| Troubleshooting | troubleshooting.md | Fix errors |
Templates
| Template | When to Use |
|---|---|
| CreateTableMigration.php.md | New table |
| ModifyTableMigration.php.md | Alter table |
| PivotTableMigration.php.md | Many-to-many |
| Seeder.php.md | Seed patterns |
| MigrationTest.php.md | Test migrations |
Quick Reference
Create Table
Schema::create('posts', function (Blueprint $table) {
$table->id();
$table->foreignId('user_id')->constrained()->cascadeOnDelete();
$table->string('title');
$table->text('content');
$table->enum('status', ['draft', 'published'])->default('draft');
$table->timestamps();
$table->softDeletes();
$table->index(['user_id', 'status']);
});
Modify Table
Schema::table('posts', function (Blueprint $table) {
$table->string('slug')->after('title')->unique();
$table->boolean('featured')->default(false);
});
Commands
php artisan make:migration create_posts_table
php artisan migrate
php artisan migrate:rollback --step=1
php artisan migrate:fresh --seed
Best Practices
DO
- Use
foreignId()->constrained()for foreign keys - Add composite indexes for common queries
- Test down() method before deploying
- Use
--pretendto preview SQL
DON'T
- Modify already-deployed migrations
- Forget down() method
- Use raw SQL without Schema Builder
- Skip indexes on foreign keys
Laravel 13 Notes
Schema::ensureVectorExtensionExists() (pgvector)
Laravel 13 exposes a helper to enable the pgvector extension on PostgreSQL from a migration. Useful for embeddings and semantic search.
use Illuminate\Support\Facades\Schema;
return new class extends Migration {
public function up(): void
{
Schema::ensureVectorExtensionExists();
Schema::create('documents', function (Blueprint $table) {
$table->id();
$table->text('content');
$table->vector('embedding', dimensions: 1536)->index(); // OpenAI text-embedding-3-small; HNSW cosine vector index
$table->timestamps();
// equivalent: $table->vectorIndex('embedding'); — removal: dropVectorIndex() (13.30+)
});
}
};
vector columns/indexes also work on MariaDB 11.7+ (no extension needed). See [[laravel-vector-search]] for whereVectorSimilarTo() queries.
What's new in Schema Builder 13.x
$table->foreignUuidFor(User::class)(13.9+) andforeignUlidFor()(13.25+)- Lock-free indexes:
$table->string('email')->unique()->online();(PostgreSQL / SQL Server) ->inplace()(13.33+, MySQL) on an index or foreign key for theINPLACEDDL algorithm