Seeders
Overview
Seeders populate the database with initial or reference data required for the application to function. In Sutomo, seeders are organized by domain matching the model structure — each domain has its own seeder directory with individual seeders for specific entities, coordinated by a RunnerSeeder.
Why Use Seeders?
- Essential reference data — Genders, Religions, Ethnicities, Localizations must exist before any user can set their profile
- Demo/development data — Dummy schools, classes, students, and hiring pipelines for testing
- Setup automation — The setup wizard uses seeders to populate geographic data, settings, and master data
- Consistency — Ensures all environments (local, staging, production) have the same baseline data
Folder Structure
database/seeders/
├── DatabaseSeeder.php # Top-level orchestrator
├── Academic/ # Academic domain seeders
│ ├── RunnerSeeder.php
│ ├── DummySeed.php
│ ├── EnrollmentSeeder.php
│ ├── QuizSeeder.php
│ ├── SubjectSeeder.php
│ └── TranscriptSeeder.php
├── Acquisition/
│ └── RunnerSeeder.php
├── Assistant/
│ ├── RunnerSeeder.php
│ └── ChatbotTrainingSeeder.php
├── Bulletin/
│ └── AnnouncementSeeder.php
├── ContractManagement/
│ └── RunnerSeeder.php
├── Core/ # Core platform data
│ ├── RunnerSeeder.php
│ ├── BannerSeeder.php
│ ├── DepositTypeSeeder.php
│ ├── DiscountSeeder.php
│ ├── DocumentTypeSeeder.php
│ ├── EmployeeSeeder.php
│ ├── EthnicitySeeder.php
│ ├── GenderSeeder.php
│ ├── LocalizationSeeder.php
│ ├── ReligionSeeder.php
│ ├── RoleSeeder.php
│ ├── SettingSeeder.php
│ ├── ShieldSeeder.php
│ └── UserSeeder.php
├── Financial/
│ ├── RunnerSeeder.php
│ ├── FinanceSettingSeeder.php
│ ├── PaymentMethodSeeder.php
│ └── TransactionSeeder.php
├── Geographic/
│ └── RunnerSeeder.php
├── Hiring/
│ ├── RunnerSeeder.php
│ ├── ApplicantSeeder.php
│ ├── CandidateEducationSeeder.php
│ ├── CandidateExperienceSeeder.php
│ ├── CandidateSeeder.php
│ ├── HiringPipelineSeeder.php
│ ├── RequireTestSeeder.php
│ ├── TalentInterviewSeeder.php
│ └── VacancySeeder.php
├── Institution/
│ └── RunnerSeeder.php
├── News/
│ └── RunnerSeeder.php
├── Organization/
│ └── RunnerSeeder.php
├── Platform/
│ ├── AboutPageSeeder.php
│ ├── BulletinSeeder.php
│ ├── FacilitySeeder.php
│ ├── OnboardingSeeder.php
│ ├── PropertySeeder.php
│ └── RatingSeeder.php
└── Support/
└── RunnerSeeder.phpPatterns
1. RunnerSeeder Pattern
Each domain has a RunnerSeeder that calls individual seeders in the correct order. This keeps DatabaseSeeder.php clean and allows domains to manage their own dependencies.
// database/seeders/Core/RunnerSeeder.php
class RunnerSeeder extends Seeder
{
public function run(): void
{
$this->call([
GenderSeeder::class, // no dependencies
ReligionSeeder::class, // no dependencies
EthnicitySeeder::class, // no dependencies
RoleSeeder::class, // must run before UserSeeder & EmployeeSeeder
UserSeeder::class,
EmployeeSeeder::class,
SettingSeeder::class,
// ...
]);
}
}2. updateOrCreate — Idempotent Seeders
Reference data uses updateOrCreate so seeders can be run multiple times without creating duplicates:
class GenderSeeder extends Seeder
{
public function run(): void
{
foreach ($this->data() as $item) {
Gender::query()->updateOrCreate(
['code' => $item['code']], // unique match
['name' => $item['name']], // update or set
);
}
}
private function data(): array
{
return [
['code' => 'male', 'name' => ['en' => 'Male', 'id' => 'Laki-laki']],
['code' => 'female', 'name' => ['en' => 'Female', 'id' => 'Perempuan']],
];
}
}3. ShieldSeeder — Role & Permission Setup
The ShieldSeeder ensures standard roles and custom permissions exist. It uses firstOrCreate to safely run alongside Filament Shield's own role generation.
class ShieldSeeder extends Seeder
{
public function run(): void
{
$superUserRole = Role::firstOrCreate([
'name' => 'super_user', 'guard_name' => 'web',
]);
$importPerm = Permission::firstOrCreate([
'name' => 'import_data', 'guard_name' => 'web',
]);
$superUserRole->givePermissionTo($importPerm);
}
}4. DummySeed — Development Data
Dummy seeders use factories to generate realistic test data for development and staging environments.
class DummySeed extends Seeder
{
public function run(): void
{
School::factory()->count(3)->create();
Teacher::factory()->count(20)->create();
Student::factory()->count(200)->create();
}
}Key Files
database/seeders/
├── DatabaseSeeder.php # Top-level seeder — calls all RunnerSeeders
├── Core/
│ ├── RunnerSeeder.php # Core domain orchestrator
│ ├── GenderSeeder.php # Gender reference data
│ ├── ReligionSeeder.php # Religion reference data
│ ├── EthnicitySeeder.php # Ethnicity reference data
│ ├── RoleSeeder.php # Spatie roles
│ ├── ShieldSeeder.php # Custom permissions
│ ├── UserSeeder.php # Default admin users
│ ├── SettingSeeder.php # Default system settings
│ └── LocalizationSeeder.php # Available locales
├── Geographic/
│ └── RunnerSeeder.php # Countries, states, cities
├── Institution/
│ └── RunnerSeeder.php # Schools, education levels
├── Organization/
│ └── RunnerSeeder.php # Departments, positions
├── Hiring/
│ └── RunnerSeeder.php # Hiring pipelines, candidates
├── Academic/
│ ├── RunnerSeeder.php # Academic data
│ ├── DummySeed.php # Development dummy data
│ └── ...
└── ...