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 BlueprintKegunaanSQL (SQLite)
$table->id()primary key auto-increment, alias bigIncrements('id')integer primary key autoincrement
$table->string('judul', 120)teks pendek dengan batas panjangvarchar
$table->text('isi')teks panjang tanpa batas praktistext
$table->integer('views')bilangan bulat 32-bitinteger
$table->bigInteger('total')bilangan bulat 64-bitinteger
$table->decimal('harga', 10, 2)angka persis dua desimal, cocok untuk uangnumeric
$table->boolean('published')nilai benar atau salahtinyint(1)
$table->date('terbit_pada')tanggal tanpa waktudate
$table->dateTime('jadwal')tanggal beserta waktudatetime
$table->timestamp('dilihat')titik waktu; timestamp di MySQLdatetime
$table->json('meta')struktur JSONtext
$table->jsonb('meta')JSON binary, unggul di PostgreSQLtext
$table->enum('status', [...])pilihan terbatasvarchar + check (in (...))
$table->uuid('uid')identifier UUID 36 karaktervarchar
$table->foreignId('user_id')kolom relasi; bigint unsigned di MySQLinteger

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():

php
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:

bash
php artisan db:table posts

Output yang Dihasilkan:

text
  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:

ModifierEfekBukti di SQLite
->nullable()mengizinkan nilai NULLharga numeric, nullable
->default($nilai)menetapkan nilai bawaanstok integer ... '0'
->unsigned()menolak bilangan negatifdiabaikan (efektif di MySQL)
->comment('...')keterangan kolomdiabaikan (efektif di MySQL)
->after('kolom') / ->first()mengatur posisi kolomdiabaikan (efektif di MySQL)
->useCurrent()nilai bawaan CURRENT_TIMESTAMPdefault CURRENT_TIMESTAMP

Berikut migration kedua yang memusatkan penggunaan modifier pada tabel products:

php
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:

text
  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.