Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Populate Laravel Package

laragear/populate

Populate makes it easy to fill Laravel databases with realistic fake data using dedicated populators. It understands model relationships, so you can generate consistent records for demos, tests, and local development without writing tedious seeders or manual fixtures.

View on GitHub
Deep Wiki
Context7

Getting Started

Install the package with Composer and let Laravel's package discovery wire it up:

composer require laragear/populate --dev

Then publish the config so you can see what the package expects:

php artisan vendor:publish --tag=populate.config

Where to look first:

  1. config/populate.php — the list of registered populators (the package's equivalent of seeders), plus any connection/behaviour defaults.
  2. php artisan populate --help — the authoritative list of flags for your installed version; the signature is the fastest way to learn what the command supports (--class, --database, --seed, etc.).
  3. vendor/laragear/populate/src/ — the Populator base class and the underlying command. Both are small and readable; reading them beats guessing from the README.

First use case: write one populator that wraps an existing factory and run it against a scratch database.

namespace Database\Populators;

use Laragear\Populate\Populator;
use App\Models\User;

class UserPopulator extends Populator
{
    public function populate(): void
    {
        User::factory()->count(50)->create();
    }
}

Register it in config/populate.php, then:

php artisan migrate:fresh && php artisan populate

That is the whole loop: factories do the work, populators decide the order. If you already have model factories, you are 90% done on day one — Populate replaces hand-rolled seeder classes rather than replacing factories.

Implementation Patterns

Keep populators as thin ordering layers. A populator should rarely contain data definitions; it should call factories and coordinate counts. Anything reusable (attribute shapes, states, relationships) belongs in the factory, where php artisan make:factory and ->state() already give you composability.

Order is the dependency graph. Populators run sequentially, so declare them parent-first: users → posts → comments. For relations you don't want to hand-wire, use the factory relationship helpers:

Post::factory()
    ->count(20)
    ->for(User::factory())      // or ->recycle($users)
    ->create();

recycle() is usually better than for() for child rows — it reuses a small pool of already-persisted parents instead of creating one per child.

Separate local dev data from test data.

  • Local/demo: a "rich" set of populators with realistic volumes, run manually or via a Composer script:
    "scripts": { "db:demo": ["@php artisan migrate:fresh", "@php artisan populate"] }
    
  • Tests: keep using RefreshDatabase + targeted factories. Reserve populators for the handful of tests that need a realistic fixture set (search indexes, reporting queries, pagination edge cases) — calling $this->artisan('populate') once in setUp is far cheaper than writing them by hand.

Make it idempotent if you plan to run it against a database you don't drop first. Guard at the top of each populator:

if (User::query()->exists()) {
    return;
}

Otherwise populate on a non-fresh DB will either duplicate rows or blow up on unique constraints, and you'll waste an afternoon on the error message rather than the cause.

Pass context between populators via the container rather than globals — resolve a shared value object (or app()->instance()) in the first populator and read it in later ones. This keeps cross-populator coupling explicit when, say, posts need to reference specific users created earlier.

CI and preview environments. Because populators are plain classes registered in config, they run fine in a pipeline. Pair them with a dedicated connection:

php artisan populate --database=demo

Keep them out of the production image by requiring the package with --dev and guarding the command in AppServiceProvider::boot() ($this->app->isProduction() → don't register).

Gotchas and Tips

v2.0.2 — command registration changed. This release removes the [AsCommand] attribute that "for some reason duplicated the command registration." Practical consequences:

  • If you were on 2.0.0/2.0.1, php artisan list may have shown populate more than once, and command lookup could be ambiguous depending on how you invoked it. After upgrading, confirm you see exactly one entry.
  • If you extended or replaced the package command and relied on attribute-based discovery to pick it up, you now need to register it explicitly in a service provider (or via commands() in bootstrap/app.php on Laravel 11+). Check php artisan list after upgrading — a silently missing command is the failure mode here.
  • No API, config, or data-shape changes are implied by this patch, so populators themselves should need no edits.

Factory existence is a hard requirement. Populate composes factories; it does not replace them. Model::factory() failing with "factory not found" means you skipped make:factory or the model doesn't use HasFactory.

Large counts. ->count(100_000) in one call will spike memory and can blow past max_execution_time in a container. Chunk it:

for ($i = 0; $i < 100; $i++) {
    Order::factory()->count(1_000)->create();
}

Unique columns. unique() on a factory attribute draws from Faker's unique pool, which is per-process. Across multiple populators in one run you're fine; across repeated runs against the same DB you are not — use Sequence or a distinct prefix per run.

Config caching bites. Registered populators come from config. After adding a class, php artisan config:clear (or re-run config:cache) before debugging why it "isn't being called." This is the single most common false alarm with config-driven packages.

Foreign keys and truncation. migrate:fresh handles ordering; db:wipe plus manual truncation does not. If you see FK violations only in CI, suspect the cleanup path, not the populators.

Extension points: the Populator base class (subclass for shared setup/teardown), the config file (registration, defaults), and service-container bindings (swap or decorate the command if you need custom flags). Prefer subclassing the base class over copying logic between populators — that's where the package's ergonomics actually pay off as your dataset grows.

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
jinas/dhivatar
store-doc/laravel-storage-driver
plus-it/laravel-translation-manager
diephp/perhaps
diephp/telegraph
osmaviation/spreadsheet
microsoft/fluentui-system-icons
mmccook/php-json-canonicalization-scheme
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console
pnscripts/filament-broadquill-lite
pnscripts/laravel-sentfold-lite
vleap/mx-sdk-laravel-internal
twidpay/utils
htetmyathlaing/scout-elasticsearch-driver
artisan-toolbox/front-awesome
ls/client-assistant
users-au/laravel-client
cgv/localized-resource