Membuat tabel bukan hanya soal memilih nama kolom, tetapi juga memilih tipe data yang tepat untuk setiap kolom. Schema builder menyediakan puluhan method seperti $table->string(), $table->decimal(), atau $table->json() yang pada akhirnya diterjemahkan menjadi tipe SQL native oleh driver database yang sedang kita pakai. Tipe SQL yang sama bisa berbeda bentuk antara SQLite, MySQL, dan PostgreSQL. Chapter ini memetakan method-method tersebut ke SQL nyata, lalu membuktikan petanya lewat migration sungguhan yang dijalankan pada SQLite — database yang kita pakai sepanjang Course ini.
Peta Method ke Tipe SQL #
Tabel berikut merangkum method kolom yang paling sering dipakai beserta SQL yang benar-benar dihasilkan SQLite. Semua barisnya kita verifikasi langsung dari pernyataan CREATE TABLE yang tersimpan di sqlite_master, bukan dari dugaan:
| Method Blueprint | Kegunaan | SQL (SQLite) |
|---|---|---|
$table->id() | primary key auto-increment, alias bigIncrements('id') | integer primary key autoincrement |
$table->string('judul', 120) | teks pendek dengan batas panjang | varchar |
$table->text('isi') | teks panjang tanpa batas praktis | text |
$table->integer('views') | bilangan bulat 32-bit | integer |
$table->bigInteger('total') | bilangan bulat 64-bit | integer |
$table->decimal('harga', 10, 2) | angka persis dua desimal, cocok untuk uang | numeric |
$table->boolean('published') | nilai benar atau salah | tinyint(1) |
$table->date('terbit_pada') | tanggal tanpa waktu | date |
$table->dateTime('jadwal') | tanggal beserta waktu | datetime |
$table->timestamp('dilihat') | titik waktu; timestamp di MySQL | datetime |
$table->json('meta') | struktur JSON | text |
$table->jsonb('meta') | JSON binary, unggul di PostgreSQL | text |
$table->enum('status', [...]) | pilihan terbatas | varchar + check (in (...)) |
$table->uuid('uid') | identifier UUID 36 karakter | varchar |
$table->foreignId('user_id') | kolom relasi; bigint unsigned di MySQL | integer |
Keluarga tipe lain mengikuti pola yang sama dan sudah ikut kita uji: tinyInteger(), smallInteger(), dan mediumInteger() semuanya menjadi integer; char() menjadi varchar; mediumText() dan longText() menjadi text; float() dan double() tetap float/double; binary() menjadi blob; sedangkan ipAddress() dan macAddress() menjadi varchar. Dokumentasi resmi memuat daftar tipe kolom yang jauh lebih panjang
untuk kasus khusus semacam morphs() dan rememberToken().
Migration Contoh: Tabel posts #
Daripada hanya membayangkan tabel di atas, mari kita buktikan dengan migration asli untuk tabel posts penyimpan tulisan blog. Buat migration seperti yang sudah kita pelajari di chapter Membuat Migration
, lalu isi method up():
Schema::create('posts', function (Blueprint $table) {
$table->id();
$table->foreignId('user_id');
$table->string('judul', 120);
$table->string('slug')->unique();
$table->text('isi');
$table->integer('views')->default(0);
$table->decimal('harga', 10, 2)->nullable();
$table->boolean('published')->default(false);
$table->json('meta')->nullable();
$table->timestamps();
$table->softDeletes();
});Setelah menjalankan php artisan migrate, perintah db:table posts memperlihatkan skema nyata yang dibuat SQLite:
php artisan db:table postsOutput yang Dihasilkan:
main.posts .................................................................
Columns .................................................................. 12
Column ................................................................ Type
id integer, autoincrement .......................................... integer
user_id integer .................................................... integer
judul varchar ...................................................... varchar
slug varchar ....................................................... varchar
isi text .............................................................. text
views integer .................................................. '0' integer
harga numeric, nullable ............................................ numeric
published tinyint ........................................... '0' tinyint(1)
meta text, nullable ................................................... text
created_at datetime, nullable ..................................... datetime
updated_at datetime, nullable ..................................... datetime
deleted_at datetime, nullable ..................................... datetime
Index ......................................................................
posts_slug_unique slug .............................................. unique
primary id ......................................................... primary Perhatikan beberapa bukti pemetaan: kolom id menjadi integer dengan autoincrement, judul menjadi varchar, published menjadi tinyint(1), dan harga menjadi numeric. Modifier ->default(0) terlihat sebagai '0' di samping kolom views. Perintah db:table seperti ini layak dihafal karena menjadi cara tercepat memeriksa skema nyata tanpa membuka database client.
Modifier Kolom #
Modifier dirantai setelah method kolom untuk mengatur perilaku lanjutan. Tabel berikut merangkum modifier yang paling penting beserta efek nyatanya:
| Modifier | Efek | Bukti di SQLite |
|---|---|---|
->nullable() | mengizinkan nilai NULL | harga numeric, nullable |
->default($nilai) | menetapkan nilai bawaan | stok integer ... '0' |
->unsigned() | menolak bilangan negatif | diabaikan (efektif di MySQL) |
->comment('...') | keterangan kolom | diabaikan (efektif di MySQL) |
->after('kolom') / ->first() | mengatur posisi kolom | diabaikan (efektif di MySQL) |
->useCurrent() | nilai bawaan CURRENT_TIMESTAMP | default CURRENT_TIMESTAMP |
Berikut migration kedua yang memusatkan penggunaan modifier pada tabel products:
Schema::create('products', function (Blueprint $table) {
$table->id();
$table->string('nama');
$table->string('kode')->nullable();
$table->integer('stok')->default(0);
$table->enum('status', ['aktif', 'nonaktif'])->default('aktif');
$table->decimal('harga', 10, 2)->unsigned();
$table->timestamp('dilihat_pada')->useCurrent();
$table->timestamps();
});Output db:table products memperlihatkan efek setiap modifier:
main.products ..............................................................
Columns ................................................................... 9
Column ................................................................ Type
id integer, autoincrement .......................................... integer
nama varchar ....................................................... varchar
kode varchar, nullable ............................................. varchar
stok integer ................................................... '0' integer
status varchar ............................................. 'aktif' varchar
harga numeric ...................................................... numeric
dilihat_pada datetime ........................... CURRENT_TIMESTAMP datetime
created_at datetime, nullable ..................................... datetime
updated_at datetime, nullable ..................................... datetime Kolom kode boleh kosong, stok dan status punya nilai bawaan, sedangkan dilihat_pada terisi waktu saat ini otomatis. Menariknya, enum di SQLite tidak menjadi tipe tersendiri melainkan varchar dengan check constraint — pernyataan CREATE TABLE aslinya memuat check ("status" in ('aktif', 'nonaktif')), sehingga nilai di luar daftar tetap ditolak.
Helper timestamps() dan softDeletes() #
Dua helper di akhir migration tadi menyembunyikan pekerjaan yang sering berulang. Method timestamps() membuat kolom created_at dan updated_at bertipe datetime yang boleh NULL, lalu Eloquent mengisinya otomatis setiap model dibuat atau diperbarui. Method softDeletes() menambah satu kolom deleted_at; model yang memakai trait SoftDeletes tidak menghapus baris, melainkan mengisi kolom tersebut sehingga data masih bisa dipulihkan. Perilaku lengkap keduanya kita bahas di Section Eloquent ORM
.
Skema yang rapi dengan tipe kolom yang tepat adalah fondasi, tetapi tabel yang terus bertambah baris lambat laun butuh lebih dari itu: kolom pencarian perlu diindeks supaya query tetap cepat. Cara menambahkan index, unique, dan composite index adalah topik chapter berikutnya.