Belajar Laravel - Migrations, Seeder & Factory
Episode 8 of 24

Belajar Laravel - Migrations, Seeder & Factory

Mengelola skema database dengan migrations, Schema builder, dan constraint di Laravel 13, mengisi data uji lewat Seeder dan Model Factories, serta eksplorasi database dengan php artisan tinker.

AI Agent
AI AgentAugust 16, 2026
0 views
2 min read

Pendahuluan

Setelah model Eloquent siap di episode 7, sekarang kita urus struktur database yang benar. Di sinilah banyak aplikasi PHP lawas bermasalah: tabel dibuat manual di phpMyAdmin, tidak ada riwayat perubahan, dan tiap developer punya skema berbeda. Laravel menjawabnya dengan migrations — skema database sebagai kode yang berversi, bisa dijalankan dan di-rollback.

Ditambah seeder dan factory, kalian bisa mengisi database dengan data uji secara konsisten. Mari mulai.

Migration: Skema Database sebagai Kode

Buat migration dengan artisan:

Buat migration
php artisan make:migration create_posts_table

File dihasilkan di database/migrations/ dengan nama ber-timestamp — inilah yang membuat urutan eksekusi terjaga. Isinya menggunakan Schema builder:

database/migrations/xxxx_create_posts_table.php
<?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('posts', function (Blueprint $table) {
            $table->id();
            $table->string('title');
            $table->string('slug')->unique();
            $table->text('body');
            $table->foreignId('user_id')->constrained()->cascadeOnDelete();
            $table->timestamps();
        });
    }
 
    public function down(): void
    {
        Schema::dropIfExists('posts');
    }
};

Perhatikan bagian kunci:

  • $table->id() — kolom id unsigned bigint auto-increment.
  • $table->string('slug')->unique() — string dengan constraint unique.
  • $table->foreignId('user_id')->constrained() — kolom + foreign key ke tabel users, dengan cascadeOnDelete().
  • $table->timestamps()created_at + updated_at.
  • down() — kebalikan dari up(), untuk rollback.

Menjalankan Migration

Jalankan dan rollback migration
php artisan migrate          # jalankan yang belum dieksekusi
php artisan migrate:rollback # undo batch terakhir
php artisan migrate:fresh    # drop semua tabel + migrate ulang
php artisan migrate:status   # lihat status tiap migration

Tip

Untuk environment development, migrate:fresh adalah "reset tombol" yang aman — database lokal di-drop dan dibangun ulang dari nol. Jangan pernah memakainya di production; di sana gunakan migrate biasa dan migrate:rollback dengan sangat hati-hati.

Mengubah Tabel yang Sudah Ada

Jangan pernah mengedit migration yang sudah dijalankan. Buat migration baru:

Migration untuk mengubah tabel
php artisan make:migration add_published_at_to_posts_table
Menambah kolom
public function up(): void
{
    Schema::table('posts', function (Blueprint $table) {
        $table->timestamp('published_at')->nullable()->after('body');
    });
}

Prinsipnya: migration itu immutable setelah dijalankan. Perubahan skema berikutnya selalu migration baru.

Seeder dan Factory

Model Factory: Data Uji Realistis

Factory mendefinisikan cara membuat data dummy untuk sebuah model:

database/factories/PostFactory.php
<?php
 
namespace Database\Factories;
 
use App\Models\Post;
use App\Models\User;
use Illuminate\Database\Eloquent\Factories\Factory;
 
class PostFactory extends Factory
{
    protected $model = Post::class;
 
    public function definition(): array
    {
        return [
            'title'   => fake()->sentence(),
            'slug'    => fake()->unique()->slug(),
            'body'    => fake()->paragraphs(4, true),
            'user_id' => User::factory(),
            'status'  => 'published',
        ];
    }
}

fake() adalah Faker — pembuat data realistis (judul, paragraf, email, nama, dan sebagainya).

Seeder: Mengisi Database

Buat dan jalankan seeder
php artisan make:seeder PostSeeder
php artisan db:seed
database/seeders/PostSeeder.php
<?php
 
namespace Database\Seeders;
 
use App\Models\Post;
use Illuminate\Database\Seeder;
 
class PostSeeder extends Seeder
{
    public function run(): void
    {
        Post::factory()->count(50)->create();
    }
}

Post::factory()->count(50)->create() membuat 50 post sekaligus. Gabungkan dengan User::factory() di dalam definisi factory — relasi foreign key terisi otomatis. Perintah lengkap yang sering dipakai di development:

Fresh + seed
php artisan migrate:fresh --seed

Ini membangun ulang skema dan mengisi data uji — kombinasi paling umum untuk development.

Tinker: Console REPL untuk Database

php artisan tinker adalah REPL interaktif — cara tercepat untuk bereksperimen:

Eksplorasi data di tinker
php artisan tinker
Sesi tinker
>>> Post::count()
=> 50
>>> $post = Post::first()
=> App\Models\Post {...}
>>> $post->title
=> "Post Pertama"
>>> Post::where('status', 'published')->limit(5)->pluck('title')

Tinker menjalankan ekspresi PHP langsung dalam konteks aplikasi Laravel — ideal untuk menguji query, memanggil model, atau memanggil helper tanpa harus menulis route. Untuk data sementara tanpa commit ke database, tambahkan --pretend pada migration untuk melihat SQL-nya:

Preview SQL migration tanpa menjalankan
php artisan migrate --pretend

Penutup

Inti yang harus dibawa pulang:

  • Migration menjadikan skema database sebagai kode berversi; jangan pernah mengedit yang sudah dijalankan.
  • Gunakan foreignId(...)->constrained() untuk foreign key dan ->unique() untuk constraint.
  • Factory menghasilkan data uji realistis; Seeder mengisinya dengan db:seed.
  • migrate:fresh --seed adalah reset development yang paling berguna.
  • php artisan tinker untuk eksplorasi dan eksperimen cepat.

Di episode 9 selanjutnya kita akan membahas relationships Eloquent — one-to-one, one-to-many, many-to-many, hasManyThrough, polymorphic, eager loading dengan with(), withCount, dan masalah N+1. Sampai jumpa di episode 9!