Mengelola skema database dengan migrations, Schema builder, dan constraint di Laravel 13, mengisi data uji lewat Seeder dan Model Factories, serta eksplorasi database dengan php artisan tinker.

Setelah model Eloquent siap di episode 7, sekarang kita urus struktur database yang benar. Di sinilah banyak aplikasi PHP lawas bermasalah: tabel dibuat manual di phpMyAdmin, tidak ada riwayat perubahan, dan tiap developer punya skema berbeda. Laravel menjawabnya dengan migrations — skema database sebagai kode yang berversi, bisa dijalankan dan di-rollback.
Ditambah seeder dan factory, kalian bisa mengisi database dengan data uji secara konsisten. Mari mulai.
Buat migration dengan artisan:
php artisan make:migration create_posts_tableFile dihasilkan di database/migrations/ dengan nama ber-timestamp — inilah yang membuat urutan eksekusi terjaga. Isinya menggunakan Schema builder:
<?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::create('posts', function (Blueprint $table) {
$table->id();
$table->string('title');
$table->string('slug')->unique();
$table->text('body');
$table->foreignId('user_id')->constrained()->cascadeOnDelete();
$table->timestamps();
});
}
public function down(): void
{
Schema::dropIfExists('posts');
}
};Perhatikan bagian kunci:
$table->id() — kolom id unsigned bigint auto-increment.$table->string('slug')->unique() — string dengan constraint unique.$table->foreignId('user_id')->constrained() — kolom + foreign key ke tabel users, dengan cascadeOnDelete().$table->timestamps() — created_at + updated_at.down() — kebalikan dari up(), untuk rollback.php artisan migrate # jalankan yang belum dieksekusi
php artisan migrate:rollback # undo batch terakhir
php artisan migrate:fresh # drop semua tabel + migrate ulang
php artisan migrate:status # lihat status tiap migrationTip
Untuk environment development, migrate:fresh adalah "reset tombol" yang aman — database lokal di-drop dan dibangun ulang dari nol. Jangan pernah memakainya di production; di sana gunakan migrate biasa dan migrate:rollback dengan sangat hati-hati.
Jangan pernah mengedit migration yang sudah dijalankan. Buat migration baru:
php artisan make:migration add_published_at_to_posts_tablepublic function up(): void
{
Schema::table('posts', function (Blueprint $table) {
$table->timestamp('published_at')->nullable()->after('body');
});
}Prinsipnya: migration itu immutable setelah dijalankan. Perubahan skema berikutnya selalu migration baru.
Factory mendefinisikan cara membuat data dummy untuk sebuah model:
<?php
namespace Database\Factories;
use App\Models\Post;
use App\Models\User;
use Illuminate\Database\Eloquent\Factories\Factory;
class PostFactory extends Factory
{
protected $model = Post::class;
public function definition(): array
{
return [
'title' => fake()->sentence(),
'slug' => fake()->unique()->slug(),
'body' => fake()->paragraphs(4, true),
'user_id' => User::factory(),
'status' => 'published',
];
}
}fake() adalah Faker — pembuat data realistis (judul, paragraf, email, nama, dan sebagainya).
php artisan make:seeder PostSeeder
php artisan db:seed<?php
namespace Database\Seeders;
use App\Models\Post;
use Illuminate\Database\Seeder;
class PostSeeder extends Seeder
{
public function run(): void
{
Post::factory()->count(50)->create();
}
}Post::factory()->count(50)->create() membuat 50 post sekaligus. Gabungkan dengan User::factory() di dalam definisi factory — relasi foreign key terisi otomatis. Perintah lengkap yang sering dipakai di development:
php artisan migrate:fresh --seedIni membangun ulang skema dan mengisi data uji — kombinasi paling umum untuk development.
php artisan tinker adalah REPL interaktif — cara tercepat untuk bereksperimen:
php artisan tinker>>> Post::count()
=> 50
>>> $post = Post::first()
=> App\Models\Post {...}
>>> $post->title
=> "Post Pertama"
>>> Post::where('status', 'published')->limit(5)->pluck('title')Tinker menjalankan ekspresi PHP langsung dalam konteks aplikasi Laravel — ideal untuk menguji query, memanggil model, atau memanggil helper tanpa harus menulis route. Untuk data sementara tanpa commit ke database, tambahkan --pretend pada migration untuk melihat SQL-nya:
php artisan migrate --pretendInti yang harus dibawa pulang:
foreignId(...)->constrained() untuk foreign key dan ->unique() untuk constraint.db:seed.migrate:fresh --seed adalah reset development yang paling berguna.php artisan tinker untuk eksplorasi dan eksperimen cepat.Di episode 9 selanjutnya kita akan membahas relationships Eloquent — one-to-one, one-to-many, many-to-many, hasManyThrough, polymorphic, eager loading dengan with(), withCount, dan masalah N+1. Sampai jumpa di episode 9!