evotodi/seed-bundle
Symfony/Doctrine bundle for loading and unloading seed data before your initial production push. Define seed commands with ordering to populate tables like states or initial admin users, unlike DoctrineFixturesBundle, which targets development.
Architecture fit — this is not a Laravel package. evotodi/seed-bundle is a Symfony bundle built on Symfony's Kernel/Bundle registration model, Symfony Console commands, and Doctrine ORM/DBAL. Its concrete dependencies are:
Evotodi\SeedBundle\Command\Seed, which is a Symfony Command.EntityManager and a Symfony password-encoder service injected via the DI container.config/services.yaml and the Symfony command registry (bin/console seed:load, seed:user, etc.).Laravel has no bundle kernel, no config/bundles.php, and no services.yaml. It ships Illuminate\Console\Command, Eloquent, and its own container. Installing this package into a Laravel app would produce a dependency whose commands never register, whose base class cannot resolve its injected EntityManager the way it expects, and whose assumptions (Doctrine entities, Symfony password hashing) do not match Eloquent models and Laravel's Hash facade. Laravel does consume some Symfony components (console, http-foundation), but "uses Symfony components" is not the same as "can boot a Symfony bundle."
Integration feasibility. For a Laravel codebase: effectively zero without forking and rewriting the command base class, the DI wiring, and the persistence layer. At that point you have written your own seeder and are carrying the fork. For a Symfony 6/7/8 + Doctrine codebase: high — it is a small, conventional bundle with a composer require install and one namespace registration.
Technical risk.
seedName() static, config file removed, PHP 8/Symfony 6 floor). A project on this package should expect a similar jump at the next major.$this->passwordEncoder->encodePassword(...), which is the pre-Symfony-6 API; the package requires Symfony 6+. The canonical example is already wrong for its own supported versions.getOrder() sorts ascending from 0, and seeds sharing an order load "semi-randomly" per the README's own caution. This is a correctness hazard, not a cosmetic one, especially with --from.unload: the documented pattern is raw DELETE FROM user. That is a table-level wipe, not a scoped removal, and it is not wrapped in a transaction.Seed base class plus two commands), so vendoring or forking is genuinely cheap.Key questions for the team.
unload/rollback semantics at all, or is append-only, idempotent seeding sufficient?Stack fit. Reject for Laravel. There is no service provider, no facade, no php artisan vendor:publish, no config file (v6 explicitly removed it). Adopting it on Laravel means adding a Symfony Console/DI/Doctrine layer to an Eloquent application for no functional gain over php artisan db:seed.
Recommended path if the stack is Laravel — do not adopt; build native. Laravel's built-in primitives already cover the stated use case (states list, initial admin, RBAC catalog):
DatabaseSeeder plus per-domain seeder classes, invoked explicitly as a deploy step (php artisan db:seed --class=ReferenceDataSeeder --force).updateOrCreate() / upsert() for idempotent reference data — strictly better than this package's non-idempotent persist/flush loop.DatabaseSeeder is deterministic by construction, avoiding the tie-ordering hazard entirely.ReferenceDataUnseeder command or wrap in a transaction if needed; do not use blanket DELETE/truncate.Use this package as a requirements reference, not a dependency: its seedName / getOrder / --skip / --from / --debug / --break command surface is a useful checklist for what a homegrown reference-data command should expose.
If the organization also runs Symfony services — adopt narrowly.
composer require evotodi/seed-bundle; register the DataSeeds\ namespace in config/services.yaml if seeds should be services.DoctrineFixturesBundle for development fixtures; use this bundle only for production reference data. Do not let the boundary blur.Compatibility. PHP 8+; Symfony 6+ per v6, with README claiming 7/8 support. Doctrine ORM/DBAL implied. Not compatible with Laravel. Verify the released tag against README claims before committing.
Sequencing (TPM-owned).
--break on, presumably).--debug dry-run to pre-release checks before expanding the seed corpus.Maintenance. Low code volume, low change rate, one maintainer. Treat it as "stable and narrow" rather than "actively maintained." Budget for vendoring or forking on the next Symfony major, and record an owner for that responsibility. The MIT license makes the fork option real, which is the main reason the risk is tolerable at all.
Support. No commercial support. Community channel is GitHub issues on a 14-star repo — expect self-service. Ramp-up for a Symfony developer is on the order of half a day: extend Seed, implement seedName(), load(), unload(), return an exit code, register the namespace. The stale password-encoder example adds a small but real friction point that will cost someone an hour.
Scaling. Adequate for small, slow-changing lookup tables. Not designed for bulk or high-frequency data:
persist/flush loops, not batched inserts.disableDoctrineLogging() is a memory mitigation, not a throughput fix.--from combined with tied order values is documented as non-deterministic — avoid in any automated path.Failure modes.
--break, a failing seed does not halt the run; you can end deploy with a half-populated reference set and a green-ish exit.seed:user duplicates the admin user. There is no upsert/dedupe. This is the most likely production incident.DELETE FROM user wipes the table regardless of provenance. If the table mixes seeded and user-created rows, rollback destroys real data. No transaction wrapper.--from and same-order seeds can skip or reorder work unpredictably.seed: after a cache clear is called out in the README as a known gotcha.services.yaml configuration; misconfiguration fails quietly at command-discovery time rather than at boot.Ramp-up. Fast for the happy path, but the operational discipline — explicit unique ordering, --break in CI/deploy, idempotency handled by the seed author, unload treated as a loaded weapon, --debug before every run — is where incidents live. A TPM should encode that discipline in the runbook rather than assume the tool enforces it; it enforces very little.
How can I help you explore Laravel packages today?