KelasIT.com
Web Development

Laravel Migration dan Database

Kelola skema database sebagai kode: cara membuat, menjalankan, mengubah, dan membatalkan migration Laravel, tipe kolom, index, foreign key, seeder, serta praktik aman untuk tim dan produksi.

Laravel Migration dan Database

Bayangkan tim berisi lima developer. Setiap orang mengubah struktur database di komputernya sendiri lewat phpMyAdmin. Seminggu kemudian tidak ada yang tahu struktur mana yang benar, dan deploy ke server berakhir error karena kolom yang hilang. Migration menyelesaikan masalah ini: struktur database ditulis sebagai kode, disimpan di Git, dan dijalankan berurutan seperti riwayat perubahan.

Apa itu migration?

Migration adalah file PHP yang berisi dua hal:

  • up() : perubahan yang ingin diterapkan (buat tabel, tambah kolom).
  • down() : cara membatalkan perubahan itu.

Laravel mencatat migration mana yang sudah dijalankan di tabel migrations, sehingga setiap perubahan hanya diterapkan sekali dan selalu berurutan berdasarkan nama file (yang diawali timestamp).

Membuat migration

php artisan make:migration create_produk_table

Laravel menebak dari namanya: awalan create_..._table membuat kerangka pembuatan tabel. Isinya kira-kira:

public function up(): void
{
    Schema::create('produk', function (Blueprint $table) {
        $table->id();
        $table->string('nama', 100);
        $table->text('deskripsi')->nullable();
        $table->decimal('harga', 12, 2)->default(0);
        $table->unsignedInteger('stok')->default(0);
        $table->boolean('aktif')->default(true);
        $table->timestamps();
    });
}

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

Cara pintas yang sering dipakai: php artisan make:model Produk -m membuat model sekaligus migration-nya.

Menjalankan dan membatalkan

PerintahFungsi
php artisan migrateMenjalankan semua migration yang belum dijalankan
php artisan migrate:statusMelihat migration mana yang sudah/ belum jalan
php artisan migrate:rollbackMembatalkan batch terakhir
php artisan migrate:rollback --step=2Membatalkan 2 batch terakhir
php artisan migrate:freshMenghapus semua tabel lalu menjalankan ulang migration
php artisan migrate:fresh --seedSama seperti di atas, lalu mengisi data awal
Peringatan: migrate:fresh dan migrate:refresh menghapus data. Pakai hanya di lingkungan lokal. Di produksi, gunakan php artisan migrate --force yang hanya menambah perubahan baru.

Tipe kolom yang sering dipakai

MethodTipe di MySQL
id()BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY
string('nama', 100)VARCHAR(100)
text('isi') / longText()TEXT / LONGTEXT
integer(), bigInteger(), unsignedInteger()INT, BIGINT, INT UNSIGNED
decimal('harga', 12, 2)DECIMAL(12,2): gunakan untuk uang
boolean('aktif')TINYINT(1)
date(), dateTime(), timestamp()DATE, DATETIME, TIMESTAMP
json('opsi')JSON
enum('status', ['draft','terbit'])ENUM
timestamps()created_at dan updated_at
softDeletes()deleted_at untuk soft delete

Pemodifikasi: ->nullable(), ->default(x), ->unique(), ->index(), ->after('kolom'), ->comment('...').

Mengubah tabel yang sudah ada

Jangan mengedit migration lama yang sudah dijalankan oleh orang lain. Buat migration baru:

php artisan make:migration add_slug_to_produk_table --table=produk
public function up(): void
{
    Schema::table('produk', function (Blueprint $table) {
        $table->string('slug')->unique()->after('nama');
    });
}

public function down(): void
{
    Schema::table('produk', function (Blueprint $table) {
        $table->dropColumn('slug');
    });
}

Pada Laravel 10 ke bawah, mengubah tipe kolom yang sudah ada (->change()) membutuhkan paket doctrine/dbal. Mulai Laravel 11 perubahan kolom sudah didukung langsung.

Menambah kolom NOT NULL pada tabel yang sudah berisi data memerlukan nilai bawaan (->default(...)) atau dibuat nullable() dulu, kalau tidak migration akan gagal.

Index dan foreign key

Schema::create('pesanan', function (Blueprint $table) {
    $table->id();
    $table->foreignId('user_id')->constrained()->cascadeOnDelete();
    $table->string('status', 20)->index();
    $table->decimal('total', 12, 2);
    $table->timestamps();

    $table->index(['user_id', 'status']);   // index gabungan
});

foreignId('user_id')->constrained() otomatis membuat kolom bertipe sama dan constraint ke tabel users (Laravel menebak nama tabel dari nama kolom). cascadeOnDelete(), restrictOnDelete(), dan nullOnDelete() mengatur aksi saat induk dihapus. Konsep dasarnya dibahas di Memahami Primary Key dan Foreign Key.

Urutan penting: tabel yang dirujuk harus dibuat lebih dulu (timestamp migration-nya lebih awal).

Seeder dan factory

Seeder mengisi data awal atau data contoh:

php artisan make:seeder KategoriSeeder
php artisan db:seed --class=KategoriSeeder

Factory membuat data palsu realistis untuk pengembangan dan testing:

Produk::factory()->count(50)->create();

Praktik terbaik

  1. Satu migration, satu tujuan. Lebih mudah dibaca dan di-rollback.
  2. Selalu tulis down() yang benar agar rollback aman.
  3. Jangan mengubah migration yang sudah di-merge ke cabang utama. Tambah migration baru.
  4. Pisahkan perubahan skema dari perubahan data. Migrasi data besar sebaiknya memakai command atau seeder tersendiri.
  5. Uji di salinan data produksi sebelum menjalankan migration berisiko (mengubah tabel jutaan baris bisa mengunci tabel).
  6. Backup sebelum deploy yang memuat migration destruktif (dropColumn, dropTable).
  7. Commit migration bersama kode yang memakainya.

Masalah umum

GejalaPenyebab
Base table or view already existsTabel dibuat manual atau migration dijalankan sebagian. Periksa migrate:status
Cannot add foreign key constraintTipe kolom FK tidak sama dengan PK, atau tabel induk belum ada
Specified key was too long (MySQL lama)Atur Schema::defaultStringLength(191) di AppServiceProvider
Class not found saat migrateNama class tidak cocok dengan nama file, jalankan composer dump-autoload

Kesimpulan

Migration menjadikan skema database sebagai bagian dari kodebase: terversi, bisa di-review, dan bisa direproduksi di komputer mana pun. Buat migration baru untuk setiap perubahan, tulis down() dengan benar, dan jaga agar perintah destruktif tidak pernah menyentuh produksi tanpa backup.

H
Hifzon

Menulis tentang pemrograman, database, AI, dan karier di dunia IT supaya belajar terasa lebih mudah dan menyenangkan.

Komentar (0)

Komentar hanya untuk member. Masuk atau daftar gratis untuk ikut berdiskusi.

Mau belajar lebih dalam?

Course online dengan latihan coding interaktif dan sertifikat.

Lihat Course →

Gabung komunitas

Tanya jawab, info event, dan teman belajar di grup WhatsApp.

Gabung Grup