Skema yang rapi tetap kosong tanpa data. Aplikasi nyata hampir selalu butuh data awal: akun administrator, daftar kategori, provinsi, atau jenis pembayaran — data yang harus ada sebelum pengguna pertama mendaftar. Database seeder adalah class PHP yang mengisi tabel lewat kode, sehingga data awal ikut tersimpan di repositori Git, bisa ditinjau lewat code review, dan dijalankan ulang kapan pun oleh anggota tim. Chapter ini membahas anatomi seeder, cara menjalankannya dengan db:seed, serta pola migrate:fresh --seed yang menjadi perintah sehari-hari selama pengembangan.
Anatomi DatabaseSeeder #
Semua seeder tersimpan di database/seeders/ dan berawal dari satu class bawaan bernama DatabaseSeeder. Class ini adalah pintu masuk sekaligus penyusun urutan: method run() di dalamnya memanggil seeder lain lewat $this->call(). Berikut isi lengkapnya setelah kita isi:
<?php
namespace Database\Seeders;
use Illuminate\Database\Seeder;
class DatabaseSeeder extends Seeder
{
public function run(): void
{
$this->call([
UserSeeder::class,
TaskSeeder::class,
]);
}
}Array pada $this->call() dijalankan berurutan dari atas ke bawah, jadi urutan penting bila satu seeder bergantung pada hasil seeder sebelumnya — pengguna harus ada lebih dulu sebelum tugas yang menunjuknya disisipkan.
Membuat Seeder Baru #
Seeder baru dibuat lewat artisan, sama seperti migration. Kita butuh dua seeder, satu untuk data master dan satu untuk contoh data awal:
php artisan make:seeder UserSeeder
php artisan make:seeder TaskSeederOutput yang Dihasilkan:
INFO Seeder [database/seeders/UserSeeder.php] created successfully.
INFO Seeder [database/seeders/TaskSeeder.php] created successfully. Kedua berkas berisi class kosong dengan satu method run(). Kita isi UserSeeder dengan akun awal lewat model User:
<?php
namespace Database\Seeders;
use App\Models\User;
use Illuminate\Database\Seeder;
use Illuminate\Support\Facades\Hash;
class UserSeeder extends Seeder
{
public function run(): void
{
User::create([
'name' => 'Budi',
'email' => '[email protected]',
'password' => Hash::make('password-rahasia'),
]);
}
}Pemakaian model User di sini disengaja: password melewati Hash::make() sehingga tersimpan ter-hash, persis seperti alur pendaftaran normal. Untuk baris-baris sederhana, query builder juga memadai — TaskSeeder mengisi tiga tugas sekaligus lewat satu pernyataan insert():
<?php
namespace Database\Seeders;
use Illuminate\Database\Seeder;
use Illuminate\Support\Facades\DB;
class TaskSeeder extends Seeder
{
public function run(): void
{
$waktu = '2026-01-05 08:00:00';
DB::table('tasks')->insert([
['user_id' => 1, 'judul' => 'Belajar seeding Laravel', 'slug' => 'belajar-seeding-laravel', 'status' => 'selesai', 'created_at' => $waktu, 'updated_at' => $waktu],
['user_id' => 1, 'judul' => 'Menulis migration baru', 'slug' => 'menulis-migration-baru', 'status' => 'proses', 'created_at' => $waktu, 'updated_at' => $waktu],
['user_id' => 1, 'judul' => 'Review skema database', 'slug' => 'review-skema-database', 'status' => 'todo', 'created_at' => $waktu, 'updated_at' => $waktu],
]);
}
}Menjalankan db:seed #
Perintah db:seed menjalankan DatabaseSeeder, yang selanjutnya memanggil kedua seeder anak:
php artisan db:seedOutput yang Dihasilkan:
INFO Seeding database.
Database\Seeders\UserSeeder ........................................ RUNNING
Database\Seeders\UserSeeder .................................... 224 ms DONE
Database\Seeders\TaskSeeder ........................................ RUNNING
Database\Seeders\TaskSeeder ...................................... 0 ms DONE Apa yang terjadi bila perintah yang sama dijalankan dua kali? Seeder kita tidak dirancang idempotent, dan constraint dari chapter Foreign Keys langsung menampik:
INFO Seeding database.
Database\Seeders\UserSeeder ........................................ RUNNING
Illuminate\Database\UniqueConstraintViolationException
SQLSTATE[23000]: Integrity constraint violation: 19 UNIQUE constraint failed: users.email (Connection: sqlite, ...)Email [email protected] sudah ada, jadi User::create() yang kedua gagal. Bila seeder perlu aman diulang, gunakan User::firstOrCreate([...]) atau insertOrIgnore() alih-alih create() dan insert() biasa.
Menjalankan Seeder Tunggal #
Kadang kita hanya perlu menjalankan satu seeder tanpa menyentuh yang lain — misalnya setelah menambah seeder kategori baru di proyek yang datanya sudah terisi. Opsi --class memilih class tertentu:
php artisan db:seed --class=TaskSeederOutput yang Dihasilkan:
INFO Seeding database.
Database\Seeders\TaskSeeder ........................................ RUNNING
Database\Seeders\TaskSeeder ...................................... 8 ms DONE Hanya TaskSeeder yang berjalan — DatabaseSeeder beserta UserSeeder tidak tersentuh. Fitur ini juga menjadi fondasi seeder produksi yang terstruktur: setiap seeder bisa dijalankan terpisah sesuai kebutuhan tanpa mengulang data master.
migrate:fresh --seed: Perintah Sehari-hari #
Selama pengembangan, kombinasi yang paling sering dipakai adalah membangun ulang seluruh database dari nol lalu mengisinya — satu perintah, urut, dan hasilnya selalu sama:
php artisan migrate:fresh --seedOutput yang Dihasilkan:
Dropping all tables ............................................ 3.19ms DONE
INFO Preparing database.
Creating migration table ....................................... 2.52ms DONE
INFO Running migrations.
0001_01_01_000000_create_users_table ........................... 1.88ms DONE
0001_01_01_000001_create_cache_table ........................... 0.84ms DONE
0001_01_01_000002_create_jobs_table ............................ 1.61ms DONE
2026_10_13_153049_create_personal_access_tokens_table .......... 0.80ms DONE
2026_10_13_170012_create_posts_table ........................... 0.71ms DONE
2026_10_13_170036_create_products_table ........................ 0.54ms DONE
2026_10_13_170109_create_tasks_table ........................... 0.72ms DONE
2026_10_13_170140_create_comments_table ........................ 2.60ms DONE
INFO Seeding database.
Database\Seeders\UserSeeder ........................................ RUNNING
Database\Seeders\UserSeeder .................................... 214 ms DONE
Database\Seeders\TaskSeeder ........................................ RUNNING
Database\Seeders\TaskSeeder ...................................... 0 ms DONE Skema dijatuhkan, dibangun ulang migration demi migration, lalu seeder mengisinya — database lokal selalu berada di keadaan yang bisa diprediksi. Kebiasaan ini juga aman untuk demo dan pengujian otomatis, karena setiap orang mendapat data yang identik.
Seeder sangat cocok untuk data yang nilainya tetap dan jumlahnya sedikit. Begitu kita butuh puluhan data uji yang bervariasi untuk menguji pagination atau tampilan daftar, menulis baris satu per satu tidak lagi praktis — di situlah model factories berperan, topik chapter berikutnya. Daftar lengkap kemampuan seeder, termasuk memanggil seeder dari seeder lain dengan parameter, tersedia di dokumentasi seeding .