Skip to Content
LaravelMigrations

Migrations et Seeders — Laravel 12

Gestion du schéma de base de données versionné et peuplement.

🏗️ Migrations

Création

php artisan make:migration create_users_table php artisan make:migration add_avatar_to_users_table --table=users php artisan make:model Post -m # avec migration

Structure

<?php // database/migrations/2023_12_01_000000_create_users_table.php use Illuminate\Database\Migrations\Migration; use Illuminate\Database\Schema\Blueprint; use Illuminate\Support\Facades\Schema; return new class extends Migration { public function up(): void { Schema::create('users', function (Blueprint $table) { $table->id(); $table->string('name'); $table->string('email')->unique(); $table->timestamp('email_verified_at')->nullable(); $table->string('password'); $table->rememberToken(); $table->timestamps(); }); } public function down(): void { Schema::dropIfExists('users'); } };

📊 Types de colonnes

Types de base

Schema::create('posts', function (Blueprint $table) { // Numériques $table->integer('votes'); $table->bigInteger('views'); $table->decimal('price', 8, 2); $table->float('rating'); // Chaînes $table->string('title'); $table->string('slug', 100); $table->text('content'); $table->longText('description'); $table->char('status', 1); // Dates $table->date('published_at'); $table->datetime('created_at'); $table->timestamp('deleted_at')->nullable(); $table->year('birth_year'); // Booléen et binaire $table->boolean('is_active'); $table->binary('data'); // JSON et enum $table->json('settings'); $table->jsonb('metadata'); // PostgreSQL $table->enum('status', ['draft', 'published', 'archived']); // UUID et IP $table->uuid('identifier'); $table->ipAddress('visitor_ip'); $table->macAddress('device_mac'); // Géométrie (PostgreSQL) $table->geometry('coordinates'); $table->point('location'); });

Modificateurs

Schema::create('users', function (Blueprint $table) { $table->string('name')->after('id'); // Position $table->string('email')->unique(); // Unique $table->string('phone')->nullable(); // Nullable $table->integer('age')->default(18); // Valeur par défaut $table->string('slug')->index(); // Index $table->text('content')->comment('Post content'); // Commentaire // Timestamps automatiques $table->timestamps(); $table->softDeletes(); // deleted_at nullable });

🔗 Relations et contraintes

Clés étrangères

Schema::create('posts', function (Blueprint $table) { $table->id(); $table->string('title'); $table->foreignId('user_id')->constrained(); // users.id $table->foreignId('category_id')->nullable() ->constrained()->onDelete('set null'); $table->timestamps(); }); // Contrainte personnalisée $table->foreign('author_id') ->references('id') ->on('users') ->onDelete('cascade') ->onUpdate('restrict');

Tables pivot

Schema::create('role_user', function (Blueprint $table) { $table->foreignId('user_id')->constrained()->onDelete('cascade'); $table->foreignId('role_id')->constrained()->onDelete('cascade'); $table->primary(['user_id', 'role_id']); // Clé composite $table->timestamps(); });

📝 Index

Schema::create('products', function (Blueprint $table) { $table->id(); $table->string('name'); $table->string('sku')->unique(); $table->decimal('price', 8, 2); $table->integer('category_id'); $table->boolean('active'); // Index simple $table->index('name'); // Index composite $table->index(['category_id', 'active']); // Index unique $table->unique(['name', 'category_id']); // Index personnalisé $table->index('name', 'products_name_index'); // Full-text (MySQL/PostgreSQL) $table->fullText('description'); $table->fullText(['title', 'description'], 'products_search_index'); // Spatial (PostgreSQL) $table->spatialIndex('location'); });

🔧 Modifier des tables

Ajouter des colonnes

php artisan make:migration add_avatar_to_users_table --table=users
Schema::table('users', function (Blueprint $table) { $table->string('avatar')->nullable(); $table->integer('login_count')->default(0)->after('email'); $table->timestamp('last_login_at')->nullable(); });

Modifier des colonnes

// Renommer $table->renameColumn('name', 'full_name'); // Modifier type (requiert doctrine/dbal) $table->string('name', 100)->change(); $table->integer('votes')->unsigned()->change(); $table->text('description')->nullable(false)->change();

Supprimer des éléments

Schema::table('users', function (Blueprint $table) { $table->dropColumn('avatar'); $table->dropColumn(['avatar', 'login_count', 'last_login_at']); // Supprimer index $table->dropIndex('users_name_index'); $table->dropUnique('users_email_unique'); // Supprimer contraintes $table->dropForeign(['category_id']); $table->dropForeign('posts_category_id_foreign'); });

🌱 Seeders

Création

php artisan make:seeder UserSeeder php artisan make:model Category --seed

Seeder de base

<?php // database/seeders/UserSeeder.php namespace Database\Seeders; use Illuminate\Database\Seeder; use Illuminate\Support\Facades\Hash; use App\Models\User; class UserSeeder extends Seeder { public function run(): void { // Création manuelle User::create([ 'name' => 'Admin User', 'email' => 'admin@example.com', 'password' => Hash::make('password'), 'email_verified_at' => now(), ]); // Avec factory User::factory()->count(10)->create(); User::factory()->unverified()->count(5)->create(); User::factory()->admin()->create(); } }

DatabaseSeeder principal

<?php // database/seeders/DatabaseSeeder.php namespace Database\Seeders; use Illuminate\Database\Seeder; class DatabaseSeeder extends Seeder { public function run(): void { $this->call([ UserSeeder::class, CategorySeeder::class, PostSeeder::class, ]); // Ou directement // User::factory(10)->create(); } }

🏭 Factories

Création

php artisan make:factory UserFactory --model=User

Factory de base

<?php // database/factories/UserFactory.php namespace Database\Factories; use Illuminate\Database\Eloquent\Factories\Factory; use Illuminate\Support\Str; /** * @extends \Illuminate\Database\Eloquent\Factories\Factory<\App\Models\User> */ class UserFactory extends Factory { public function definition(): array { return [ 'name' => fake()->name(), 'email' => fake()->unique()->safeEmail(), 'email_verified_at' => now(), 'password' => '$2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi', 'remember_token' => Str::random(10), ]; } public function unverified(): static { return $this->state(fn (array $attributes) => [ 'email_verified_at' => null, ]); } public function admin(): static { return $this->state(fn (array $attributes) => [ 'name' => 'Admin User', 'email' => 'admin@example.com', ]); } }

Factory avec relations

<?php // database/factories/PostFactory.php namespace Database\Factories; use Illuminate\Database\Eloquent\Factories\Factory; /** * @extends \Illuminate\Database\Eloquent\Factories\Factory<\App\Models\Post> */ class PostFactory extends Factory { public function definition(): array { return [ 'title' => fake()->sentence(), 'content' => fake()->paragraphs(3, true), 'user_id' => User::factory(), 'category_id' => Category::inRandomOrder()->first()->id, 'published_at' => fake()->optional(0.7)->dateTime(), 'created_at' => fake()->dateTimeBetween('-1 year', 'now'), 'updated_at' => now(), ]; } public function published(): static { return $this->state(fn (array $attributes) => [ 'published_at' => fake()->dateTimeBetween('-6 months', 'now'), ]); } public function draft(): static { return $this->state(fn (array $attributes) => [ 'published_at' => null, ]); } }

🚀 Exécution

Migrations

php artisan migrate php artisan migrate --force # production php artisan migrate --path=database/migrations/xxx_create_users_table.php php artisan migrate:status php artisan migrate:rollback php artisan migrate:rollback --step=3 php artisan migrate:reset php artisan migrate:refresh php artisan migrate:refresh --seed php artisan migrate:fresh php artisan migrate:fresh --seed

Seeders

php artisan db:seed php artisan db:seed --class=UserSeeder php artisan db:seed --force php artisan migrate:fresh --seed

🎯 Environnements

Migrations conditionnelles

public function up(): void { if (app()->environment('local', 'testing')) { Schema::create('debug_logs', function (Blueprint $table) { $table->id(); $table->text('message'); $table->timestamps(); }); } }

Seeders par environnement

public function run(): void { $this->call([ CategorySeeder::class, UserSeeder::class, ]); if (app()->environment('local', 'testing')) { $this->call([DevelopmentDataSeeder::class]); } if (app()->environment('production')) { $this->call([ProductionDataSeeder::class]); } }

🔍 Debug

Inspection

php artisan tinker >>> Schema::getColumnListing('users'); >>> Schema::getColumnType('users', 'email'); >>> Schema::hasTable('users'); >>> Schema::hasColumn('users', 'avatar');

SQL généré

php artisan migrate --pretend php artisan migrate --pretend --path=database/migrations/xxx_create_users_table.php

Le Git pour votre base de données