LaravelMigrationDatabaseMenengah4 mnt baca

Mengubah Tabel: Tambah, Ubah, Hapus Kolom

Alter tabel yang sudah ada tanpa menghapus datanya.

Kenapa Tabel Harus Diubah Lewat Migration Baru?

Tabel posts sudah jalan di production dan berisi 10.000 artikel. Bos minta tambah kolom slug. Kamu tidak bisa mengedit migration lama create_posts_table karena migration itu sudah tercatat sebagai "sudah jalan" di semua server. Solusinya: migration baru yang mengubah tabel yang sudah ada, tanpa menyentuh datanya. Schema::table (bukan Schema::create) adalah kuncinya.

Contoh 1: Menambah Kolom

bash
php artisan make:migration add_slug_to_posts_table

Ikuti konvensi nama add_{kolom}_to_{tabel}_table agar maksudnya langsung kebaca.

File: database/migrations/2026_10_08_130000_add_slug_to_posts_table.php

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::table('posts', function (Blueprint $table) {
            $table->string('slug')->unique()->after('title');
        });
    }

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

->after('title') menempatkan kolom tepat setelah title (khusus MySQL/MariaDB). Untuk tabel yang sudah berisi data, pertimbangkan ->nullable() atau ->default(...) agar baris lama tidak error karena kolom baru yang wajib diisi.

Contoh 2: Mengubah, Menghapus, dan Me-rename Kolom

php
return new class extends Migration {
    public function up(): void
    {
        Schema::table('posts', function (Blueprint $table) {
            // ubah string(255) jadi text
            $table->text('title')->change();

            // hapus beberapa kolom sekaligus
            $table->dropColumn(['views', 'rating']);

            // rename kolom
            $table->renameColumn('body', 'konten');
        });
    }

    public function down(): void
    {
        Schema::table('posts', function (Blueprint $table) {
            $table->string('title')->change();
            $table->renameColumn('konten', 'body');
            // views dan rating tidak bisa dikembalikan datanya: biarkan hilang
        });
    }
};

Perintah rollback yang perlu kamu kenal:

bash
php artisan migrate:rollback            # batalkan batch terakhir
php artisan migrate:rollback --step=2   # batalkan 2 batch terakhir
php artisan migrate:status              # lihat migration mana yang sudah jalan

Jebakan Umum

1. ->change() butuh doctrine/dbal. Mengubah tipe kolom tidak didukung bawaan Laravel. Install dulu: composer require doctrine/dbal. Tanpa itu, error-nya membingungkan.

2. migrate:fresh menghapus SEMUA data. Perintah ini me-drop seluruh tabel lalu migrate ulang dari nol. Di local untuk development memang praktis, tapi jangan pernah dijalankan di production atau di database berisi data penting. Selalu baca ulang perintah sebelum tekan Enter.

3. Kolom baru yang NOT NULL di tabel berisi data. Menambah $table->string('slug') (wajib isi, tanpa default) ke tabel yang sudah punya 10.000 baris akan gagal di database yang ketat, karena baris lama tidak punya nilai untuk kolom baru. Solusi: ->nullable(), atau ->default(''), atau isi dulu datanya baru jadikan NOT NULL di migration terpisah.

Catatan teknis: down() tidak selalu bisa sempurna. Kolom yang di-drop tidak bisa mengembalikan datanya saat rollback, itu wajar dan harus disadari. Migration adalah version control untuk struktur, bukan backup data. Untuk keamanan data, tetap andalkan backup database sungguhan.

Tantangan

Tambah Kolom Published

Buat migration untuk menambah published_at (timestamp, nullable) ke tabel posts. Jalankan, verifikasi, lalu rollback dan verifikasi kolomnya hilang. Lalu migrate lagi.