Migration adalah mekanisme Laravel untuk mengelola perubahan skema database dalam bentuk berkas PHP yang berurutan. Topik ini membahas cara membuat berkas migration dengan Artisan, menulis definisi tabel menggunakan schema builder, menjalankan serta membatalkan migration, dan memeriksa hasilnya. Seluruh contoh diterapkan pada aplikasi catatan sehingga di akhir topik dua tabel inti, yaitu categories dan notes, sudah terbentuk dan siap digunakan oleh model Eloquent.
Migration sebagai riwayat skema#
Skema database sering berubah selama aplikasi dikembangkan: tabel ditambah, kolom disesuaikan, dan indeks dilengkapi. Apabila perubahan hanya ditulis sebagai SQL manual, setiap anggota tim dan setiap lingkungan harus menyalinnya dengan tangan, sehingga struktur database mudah menjadi tidak sinkron. Migration menyelesaikan masalah tersebut dengan menyimpan setiap perubahan skema sebagai satu berkas PHP di dalam direktori database/migrations, lalu mengeksekusi berkas-berkas itu berurutan sesuai waktu pembuatannya.
Setiap berkas migration memuat dua metode. Metode up() mendefinisikan perubahan yang ingin diterapkan, misalnya membuat tabel baru, sedangkan metode down() membalik perubahan tersebut, misalnya menjatuhkan tabel itu kembali. Laravel mencatat migration mana yang sudah dieksekusi pada tabel khusus bernama migrations di dalam database. Catatan tersebut membuat perintah migrate dapat dipanggil berulang kali tanpa risiko: hanya migration yang belum dijalankan yang dieksekusi, sedangkan migration lama dibiarkan apa adanya.
Membuat berkas migration#
Berkas migration dibuat dengan perintah make:migration. Apabila nama berkas dimulai dengan create_ dan diakhiri _table, Artisan menghasilkan kerangka Schema::create, sehingga berkasnya langsung siap diisi.
# tidak-dijalankan
# membuat dua berkas migration untuk tabel kategori dan catatan
cd ~/aplikasi-catatan
php artisan make:migration create_categories_table
php artisan make:migration create_notes_tablePerintah tersebut tidak dieksekusi pada contoh ini karena berkasnya sudah dibuat sebelumnya. Keluaran asli dari perintah itu adalah sebagai berikut.
INFO Migration [database/migrations/2026_11_03_002752_create_categories_table.php] created successfully.
INFO Migration [database/migrations/2026_11_03_002753_create_notes_table.php] created successfully. Nama berkas diawali waktu pembuatan, sehingga nilainya berbeda pada setiap lingkungan. Awalan waktu itulah yang menentukan urutan eksekusi antar-berkas: migration categories yang dibuat lebih dahulu dijalankan sebelum migration notes yang merujuk kepadanya.
Menulis skema dengan schema builder#
Isi metode up() ditulis dengan schema builder, yaitu kumpulan metode pada kelas Blueprint yang menerjemahkan pemanggilan berantai menjadi pernyataan CREATE TABLE. Definisi tabel kategori terdiri atas kolom id bertipe auto increment, kolom nama, serta dua kolom waktu bawaan.
// tidak-dijalankan
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('categories', function (Blueprint $table) {
$table->id();
$table->string('nama');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('categories');
}
};Tabel catatan memuat judul dan isi, ditambah kolom category_id yang menghubungkan setiap catatan dengan kategorinya. Metode foreignId() membuat kolom bertipe integer yang cocok dengan id milik tabel lain, sedangkan nullable() memperbolehkan catatan tanpa kategori dan constrained() menambahkan foreign key yang merujuk ke tabel categories.
// tidak-dijalankan
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('notes', function (Blueprint $table) {
$table->id();
$table->string('judul');
$table->text('isi');
$table->foreignId('category_id')->nullable()->constrained();
$table->timestamps();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('notes');
}
};Beberapa tipe kolom yang paling sering digunakan dirangkum pada tabel berikut, dan selengkapnya tercantum pada dokumentasi migration Laravel.
| Metode | Hasil di database | Kegunaan |
|---|---|---|
id() | integer, auto increment, primary key | Kunci utama tabel |
string('nama') | varchar | Teks pendek seperti nama atau judul |
text('isi') | text | Teks panjang seperti isi catatan |
foreignId('category_id') | integer, unsigned | Kolom penghubung antartabel |
boolean('aktif') | tinyint | Nilai benar atau salah |
timestamps() | dua kolom datetime | Waktu dibuat dan diperbarui |
Menjalankan migration#
Perintah migrate mengeksekusi seluruh migration yang belum tercatat pada tabel migrations. Perintah ini bersifat idempoten: apabila tidak ada migration baru, tidak ada yang dijalankan.
# mengeksekusi seluruh migration yang belum dijalankan
cd ~/aplikasi-catatan
php artisan migrate INFO Nothing to migrate.Keluaran di atas diambil dari lingkungan contoh yang seluruh migrationnya sudah pernah dieksekusi. Pada eksekusi pertama, perintah yang sama mencantumkan setiap berkas beserta lamanya. Keluaran berikut diambil saat migration contoh ini pertama kali dijalankan.
INFO Running migrations.
2026_11_03_003023_create_categories_table ...................... 1.73ms DONE
2026_11_03_003024_create_notes_table ........................... 0.93ms DONEStruktur tabel hasil migration dapat diperiksa tanpa membuka aplikasi database. Perintah db:table menampilkan daftar kolom, tipe datanya, dan kunci asing dari sebuah tabel.
# memeriksa struktur tabel notes hasil migration
cd ~/aplikasi-catatan
php artisan db:table notes
main.notes .................................................................
Columns .................................................................. 6
Column ................................................................ Type
id integer, autoincrement .......................................... integer
judul varchar ...................................................... varchar
isi text .............................................................. text
category_id integer, nullable ...................................... integer
created_at datetime, nullable ..................................... datetime
updated_at datetime, nullable ..................................... datetime
Index ......................................................................
primary id ......................................................... primary
Foreign Key .......................................... On Update / On Delete
category_id references id on categories .............. no action / no action Daftar migration beserta statusnya juga dapat dilihat kapan saja. Contoh berikut membangun ulang skema lebih dahulu dengan migrate:fresh agar seluruh migration dieksekusi pada satu batch yang sama dan daftarnya selalu sama. Status Ran berarti migration sudah dieksekusi, sedangkan Pending berarti belum.
# melihat daftar migration beserta statusnya
cd ~/aplikasi-catatan
# bangun ulang skema dari awal; keluarannya tidak diperlukan
php artisan migrate:fresh --force > /dev/null
# tampilkan daftar migration beserta statusnya
php artisan migrate:status Migration name .............................................. Batch / Status
0001_01_01_000000_create_users_table ............................... [1] Ran
0001_01_01_000001_create_cache_table ............................... [1] Ran
0001_01_01_000002_create_jobs_table ................................ [1] Ran
2026_11_03_003023_create_categories_table .......................... [1] Ran
2026_11_03_003024_create_notes_table ............................... [1] Ran
2026_11_03_085521_create_notifications_table ....................... [1] Ran
2026_11_03_212653_create_personal_access_tokens_table .............. [1] Ran Tujuh baris di atas mencakup seluruh migration proyek contoh: tiga migration bawaan Laravel untuk tabel users, cache, dan jobs, dua migration aplikasi catatan untuk tabel categories dan notes, ditambah migration notifications untuk fitur notifikasi dan personal_access_tokens untuk token API yang digunakan contoh API pada jalur ini. Seluruhnya berstatus Ran pada batch [1] karena migrate:fresh menjatuhkan semua tabel lalu mengeksekusi setiap migration sekali jalan.
Membatalkan migration#
Metode down() digunakan oleh perintah migrate:rollback, yang membatalkan migration pada batch terakhir dengan menjatuhkan tabel yang baru dibuat. Perintah ini berguna ketika definisi tabel ternyata keliru dan perlu ditulis ulang dari awal.
# tidak-dijalankan
# membatalkan batch migration terakhir
cd ~/aplikasi-catatan
php artisan migrate:rollbackPerintah di atas tidak dieksekusi pada contoh ini karena menjatuhkan tabel dan datanya. Gunakan rollback hanya pada masa pengembangan, misalnya sebelum data nyata mulai disimpan. Setelah tabel dijatuhkan, perbaiki isi migration lalu jalankan kembali php artisan migrate untuk membangun ulang skemanya.
Kesalahan umum#
Kesalahan pertama adalah mengubah isi migration yang sudah dieksekusi dan menganggap perubahan langsung muncul pada skema. Tabel migrations tetap mencatat berkas itu sebagai selesai, sehingga Laravel tidak menjalankannya lagi. Solusinya, jalankan migrate:rollback, perbaiki berkasnya, lalu jalankan kembali migrate pada lingkungan pengembangan, atau buat migration baru untuk mengubah struktur pada lingkungan yang datanya tidak boleh hilang.
Kesalahan kedua adalah membuat migration notes lebih dulu daripada categories. Foreign key pada tabel notes merujuk ke tabel categories, sehingga eksekusi gagal dengan pesan bahwa tabel yang dirujuk tidak ada. Urutkan pembuatan berkas sesuai ketergantungan tabelnya.
Kesalahan ketiga adalah menjalankan rollback di lingkungan yang berisi data penting. Perintah itu menjatuhkan tabel tanpa konfirmasi lanjutan, sehingga datanya ikut hilang. Cadangkan database sebelum membatalkan migration, atau tulis migration baru yang mengubah struktur tanpa menjatuhkan tabel.
Ringkasan#
- Migration menyimpan perubahan skema sebagai berkas PHP berurutan di
database/migrations, dengan metodeup()untuk menerapkan dandown()untuk membalik perubahan. - Schema builder menerjemahkan metode seperti
id(),string(),text(),foreignId(), dantimestamps()menjadi pernyataanCREATE TABLE. php artisan migrateidempoten: hanya migration yang belum tercatat yang dieksekusi, dan catatannya disimpan pada tabelmigrations.- Struktur hasil migration dapat diperiksa dengan
db:tabledan riwayatnya denganmigrate:status, sedangkanmigrate:rollbackmembatalkan batch terakhir.
Referensi#
- Migrations — Laravel — Dokumentasi resmi schema builder, tipe kolom, dan perintah migrate beserta variannya.
- Database: Getting Started — Laravel — Konfigurasi koneksi database SQLite yang dipakai aplikasi contoh.