cuteninja/memoria-bundle
Memoria Bundle brings lightweight memory and activity tracking to PHP applications, letting you record, inspect, and review events through simple APIs and sensible defaults so integration stays fast and configuration stays minimal.
First, calibrate expectations: despite the Laravel framing, cuteninja/memoria-bundle is a Symfony bundle, not a Laravel package. It ships no service provider, no config/memoria.php, and no Artisan command. If you are working in a Laravel codebase you will be reading this as a reference implementation or porting it, not composer require-ing it into app/. That distinction shapes everything below.
Assuming a Symfony host application:
composer.json in the repo and check the require block for symfony/framework-bundle, doctrine/orm, and doctrine/data-fixtures constraints. A bundle of this vintage (config declared in config.yml rather than config/packages/*.yaml) usually targets Symfony 3.x/4.x. Confirm the PHP constraint too — older bundles frequently pin ^7.1 or ^7.4 and will not install on PHP 8.2+ without a fork.composer require --dev cuteninja/memoria-bundle plus doctrine/doctrine-bundle, doctrine/doctrine-fixtures-bundle (or bare doctrine/data-fixtures) and a working DBAL connection. It is a dev/test-only concern; keep it out of require.config/bundles.php (CuteNinja\MemoriaBundle\MemoriaBundle::class => ['dev' => true, 'test' => true]). For Symfony <4, app/AppKernel.php.bin/console config:dump-reference memoria (or whatever the bundle alias turns out to be — check the Extension::getAlias() return value in DependencyInjection/). The README's "Fixtures declared in config.yml" is the whole contract, so the alias and the exact node name (fixtures:, fixtures_list:, data_fixtures:) are the first thing to pin down. Do not guess.bin/console list and grep for a memoria-namespaced command — typically something like memoria:fixtures:load. Run it with --help before running it for real; you want to see whether it truncates, appends, or wraps doctrine:fixtures:load.First use case: seeding reference/lookup tables (countries, currencies, roles, permission matrices) that every environment needs identically, so you stop copy-pasting DataFixture classes between projects. The value proposition is that the list of fixtures lives in YAML and the classes live in this shared bundle, so a new Cute-Ninja project gets baseline data by adding three lines of config.
Config-as-manifest. The core pattern is a declarative, ordered list of fixture service IDs or FQCNs:
# config/packages/dev/memoria.yaml
memoria:
fixtures:
- App\DataFixtures\RoleFixtures
- App\DataFixtures\CurrencyFixtures
- App\DataFixtures\DemoUserFixtures
Treat that list as the unit of intent. Ordering is meaningful and almost certainly not topologically sorted by the bundle — if DemoUserFixtures needs roles to exist, it must appear after RoleFixtures. Keep the manifest short and let each class own its own internal dependency ordering.
Split manifests per environment. Have config/packages/test/memoria.yaml declare only the deterministic, minimal set (roles, statuses, one tenant) needed for a green test suite, and let dev add the noisy demo data on top. This is the single highest-leverage thing you can do with a config-driven fixture loader — it turns "reset the test DB" into a sub-second operation instead of a multi-minute one.
Wire it into your reset loop. Whatever the command is, alias it in a Makefile or Composer script:
db-reset:
bin/console doctrine:database:drop --force --if-exists --env=test
bin/console doctrine:database:create --env=test
bin/console doctrine:migrations:migrate -n --env=test
bin/console memoria:fixtures:load -n --env=test
Then have tests depend on db-reset rather than on RefreshDatabase-style per-test transactions. Config-driven fixture loading is a bootstrapping tool; per-test isolation is a different problem and this bundle will not solve it for you.
Compose with doctrine-fixtures-bundle rather than replacing it. If Memoria's command shells out to or reuses Doctrine's fixture executor, you can mix both: legacy DoctrineFixturesBundle classes for one-off local scratch data, Memoria manifest for the shared baseline. Check whether running the Memoria command also picks up auto-registered Doctrine fixtures — if it does, your "test manifest" may silently include everything in src/DataFixtures/.
Porting to Laravel. If the goal is to reuse the idea in a Laravel app, the faithful translation is: a config/memoria.php returning an ordered array of seeder class names, a MemoriaLoadCommand extends Command with signature memoria:load {--class=}, and $this->call('db:seed', ['--class' => $fqcn]) in a loop. Keep the manifest in config/ and the classes in database/seeders/. The bundle's own PHP is worth reading for the ordering and error-handling decisions, but there is no drop-in path.
Abandonment risk is the headline. Zero stars, zero dependents, no linked CI. Treat this as vendored internal code: fork it into your org, pin it by VCS path repository, or copy the handful of relevant classes into your app. Do not build a critical seeding pipeline on a composer require that resolves from Packagist with no maintainer behind it. Check composer.json for a symfony/* upper bound — if it says ^4.0, a future Symfony upgrade will block you and there will be no upstream fix.
YAML class strings are not autoload-checked. A typo in an FQCN typically surfaces as a Class not found at load time, not at container compile time — and often only after half your fixtures have already been inserted. Clear the cache (bin/console cache:clear) after editing the manifest, since the config may be compiled into the container; a stale parameter bag will have you debugging a file the app is no longer reading.
Ordering and idempotency are your responsibility. Confirm empirically: run the command twice in a row. If the second run throws unique-constraint violations, the command appends rather than truncates, and you must front-load a purge step (doctrine:database:drop --force in dev/test, or a dedicated truncate command). Document the behavior in your Makefile so the next person does not discover it in CI.
Environment leakage. Fixture classes that reference Kernel, EntityManager, or container services must be public or explicitly tagged; in Symfony 4+ the default is private services, and a fixture declared in a manifest but not registered as a service will fail with a container error rather than a helpful message. If the bundle instantiates via new $class(), your fixtures must have no constructor dependencies at all — check this before designing fixtures that need repositories.
Debugging moves. bin/console debug:config <alias> to confirm what was actually parsed (catches YAML indentation and _defaults merge issues), bin/console debug:container --tag=doctrine.fixture.orm to see what Doctrine itself registered, and -vvv on the load command to get the stack trace. If the command exists but does nothing, the manifest key is almost certainly nested one level deeper than you wrote it.
Extension points. The two realistic override seams are (a) decorating or replacing the loader command service in services.yaml, and (b) subclassing the fixture base class if the bundle ships an abstract one with conventions (transaction wrapping, reference repository access). Read DependencyInjection/ and Command/ first — the bundle is small enough that the entire surface area is likely two or three files, and reading them will answer most of the questions above faster than any README.
How can I help you explore Laravel packages today?