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

Foundry Bundle Laravel Package

icanhazstring/foundry-bundle

Symfony bundle that integrates Foundry's PHP object factories into your app, giving you container-aware configuration for building test fixtures and model instances with less boilerplate. Use it to wire foundries as services and keep fixture setup clean and reusable across tests. Ideal for Symfony p...

View on GitHub
Deep Wiki
Context7

Getting Started

Before you composer require anything, check the package is still installable in your stack. This bundle has exactly one meaningful release history (original 2021, plus 0.3.0, which is a pure rename), 0 stars, 0 dependents, and was written against the Symfony 4/5 + Foundry 1.x era. Run a dry-run first:

composer require --dev icanhazstring/foundry-bundle:^0.3 --dry-run

If Composer resolves it, verify what it wants in return (composer why-not icanhazstring/foundry-bundle and inspect its composer.json for symfony/* and zenstruck/foundry constraints). If it blocks on Symfony 6/7 or Foundry 2.x, treat the bundle as reference source code, not a dependency — copy the compiler pass into your own src/ (see Gotchas).

0.3.0 is a breaking rename, and it is the only "feature" in the release: the namespace moved to lowercase-vendor icanhazstring\FoundryBundle and the bundle class is now simply FoundryBundle. If you are on 0.2.x, this is a find-and-replace upgrade (class reference in bundles.php, any use statements, and possibly your config key — see below). If you are new, the namespace in this assessment is now confirmed rather than inferred.

  1. Register the bundle in config/bundles.php:
return [
    // ...
    Symfony\Bundle\FrameworkBundle\FrameworkBundle::class => ['all' => true],
    Doctrine\Bundle\DoctrineBundle\DoctrineBundle::class => ['all' => true],
    Zenstruck\Foundry\ZenstruckFoundryBundle::class => ['test' => true, 'dev' => true],
    icanhazstring\FoundryBundle\FoundryBundle::class => ['test' => true],
];

Note the environment scoping: this is test/dev infrastructure and should not be loaded in prod. Note also the lowercase vendor segment — PHP namespaces are case-insensitive at runtime but Composer's PSR-4 lookup is not on case-sensitive filesystems, so copy the exact casing from the package's autoload.psr-4 block.

  1. Where to look first. Open the package in vendor/icanhazstring/foundry-bundle and read, in this order:

    • src/FoundryBundle.php and any src/DependencyInjection/*CompilerPass.php — this is the actual value of the package; it is one or two small classes.
    • src/DependencyInjection/Configuration.php — the config tree, i.e. the knobs you can set.
    • src/DependencyInjection/*Extension::getAlias() — determines your YAML key, and the 0.3.0 class rename may have changed it (default Symfony aliasing would now produce foundry, which is confusingly generic next to Zenstruck's — read it, don't guess).
    • src/Resources/config/*.yaml|php — the service definitions and tags the passes operate on.
    • README.md — the author's stated "common problems".
  2. First use case. The realistic scenario this bundle exists for: you are using Foundry factories in a Symfony app, and either (a) your factories aren't being picked up as services / can't be autowired into KernelTestCase subclasses, or (b) state (stories, Faker, proxy objects) bleeds between tests, or (c) the factory services aren't reset by services_resetter between kernel boots. Add the bundle, run an existing KernelTestCase, and see whether the previously failing factory test goes green. If it does, diff APP_ENV=test bin/console debug:container --tag=<the tag the pass adds> before/after to see exactly what changed.

Implementation Patterns

1. Autowired factories in tests. The classic day-to-day win: injecting a concrete factory into a test or a data provider rather than calling MyFactory::new() statically. Once the compiler pass tags factory services, the typical shape is:

final class OrderWorkflowTest extends KernelTestCase
{
    use ResetDatabase;

    protected function setUp(): void
    {
        self::bootKernel();
    }

    public function test_checkout(): void
    {
        $user = UserFactory::createOne();
        $order = OrderFactory::createOne(['user' => $user]);

        self::assertSame($user->getId(), $order->getUser()->getId());
    }
}

If you inject, use a static::getContainer()->get(...) lookup in setUp() or a small trait; do not constructor-inject into TestCase classes.

2. Reset-between-tests wiring. If the bundle's pass registers Foundry's stateful services as kernel.reset implementers, the pattern is to let KernelTestCase's tearDown() reset the container rather than hand-clearing things:

protected function tearDown(): void
{
    parent::tearDown(); // triggers services_resetter -> kernel.reset tags
    Story::clear();     // belt-and-braces if the bundle predates reset support
}

Verify the tag is actually applied: APP_ENV=test bin/console debug:container --tag=kernel.reset | grep -i foundry.

3. Test bootstrap config. Put the bundle's settings in config/packages/test/foundry.yaml (or when@test: in the main config), never in config/packages/foundry.yaml, since the bundle is only registered under test. Use the alias from getAlias() — re-derive it after the 0.3.0 rename rather than reusing an old key:

when@test:
    foundry:              # confirm via Extension::getAlias(), not from an old blog post
        # options as documented in Configuration.php

4. Working with Doctrine test isolation. This bundle is a helper, not a replacement for:

  • Zenstruck\Foundry\Test\ResetDatabase (schema reset between tests),
  • dama/doctrine-test-bundle (transactional wrapping),
  • Doctrine\Bundle\FixturesBundle for non-test seeding.

Typical layering: dama wraps each test in a transaction → ResetDatabase handles the first-run schema → Foundry factories create objects inside it. The bundle's passes slot underneath all of this; don't expect it to solve fixture ordering.

5. Integration with PersistentProxyObjectFactory. With proxy objects, identity-map and auto_refresh_proxies settings matter. Assert on ->getId()/->_real() deliberately, and if you see EntityNotFoundException/detached-entity errors, check the bundle's config for whatever it does to proxy refresh before chasing Doctrine.

6. Kernel boot in data providers. If you use @dataProvider with factory data, remember static providers run before setUp(); either self::bootKernel() in the provider or keep providers pure arrays and resolve factories in the test body. The bundle does not change this contract.

Gotchas and Tips

  • It is effectively unmaintained. Two releases, zero dependents, and the newest one only renames a namespace and a class. Assume no Symfony 6.4/7 support, no Foundry 2.x support, no PHP 8.2+ typing fixes. Budget a half-day to vendor it rather than debug a resolution failure.
  • 0.3.0 upgrade is mechanical but easy to get wrong. Old Icanhazstring\FoundryBundle\... references (capital I) become icanhazstring\FoundryBundle\.... After the swap, run composer dump-autoload — Composer's classmap/PSR-4 cache will happily keep serving the stale capitalised namespace until you do — then bin/console cache:clear, because compiler passes only execute on cache warmup.
  • Re-check the config alias after the rename. The extension alias is (by default) derived from the bundle class name, so FoundryBundle maps to foundry. A generic key like that is a collision waiting to happen alongside zenstruck_foundry, and an old icanhazstring_foundry: key from 0.2.x will now be silently ignored. Confirm with APP_ENV=test bin/console debug:config foundry and APP_ENV=test bin/console config:dump-reference foundry.
  • Copy-don't-require is usually correct. The whole bundle is one or two compiler passes. Vendoring means: create src/Foundry/FactoriesPass.php implementing CompilerPassInterface, $container->registerForAutoconfiguration(...)->addTag('foundry.factory') (or whatever tag the bundle uses — read the source), add it in your Kernel::build(), and drop the dependency. You get the fix plus future maintainability, and you never have to care what 0.4.0 renames.
  • Compiler pass ordering is the whole trick. If the bundle's pass runs before Doctrine's (or before Foundry's own bundle passes), tags won't be present yet. Symfony sorts by PassConfig phase (TYPE_BEFORE_OPTIMIZATION, etc.) and priority. If it silently does nothing, pass priority: <higher> or move it in your own build(). Debug with APP_ENV=test bin/console debug:container --tag=foundry.factory --show-private.
  • Environment scoping bites. Registering the bundle under test only means bin/console commands (which default to dev) can't see its config; run APP_ENV=test bin/console debug:container ... when inspecting.
  • Bundle vs AbstractBundle. If the package extends the old Symfony\Component\HttpKernel\Bundle\Bundle and you're on Symfony 6+, it still works (deprecated) — but if it implements ExtensionInterface, confirm the extension alias matches the YAML key, especially now that the class has been renamed.
  • FrameworkBundle/DoctrineBundle load order. Ensure DoctrineBundle and ZenstruckFoundryBundle are registered before this bundle in bundles.php; bundles.php insertion order influences pass collection order in older Symfony.
  • Watch for Faker locale/seed surprises. If the bundle sets faker.seed or locale, tests become order-dependent when run in parallel (paratest). Pin the seed and locale explicitly in test config.
  • Parallel test runs. ResetDatabase/transactional isolation assumes one DB per worker. If you add paratest, you need per-worker databases; nothing in this bundle helps with that, and a stale 2021-era bundle may actively conflict with dama's dynamic DB name switching.
  • Debugging checklist when "it isn't working":
    1. composer show icanhazstring/foundry-bundle — confirm 0.3.x and that the old namespace isn't still cached.
    2. APP_ENV=test bin/console debug:container --tag=<tag> — is the pass running?
    3. APP_ENV=test bin/console debug:container 'icanhazstring\FoundryBundle\' — are services registered under the new namespace?
    4. APP_ENV=test bin/console debug:config <alias> — did your YAML key land after the alias change?
    5. Add var_dump()/echo inside the pass and bin/console cache:clear — compiler passes only run on cache warmup, so always clear cache after changing bundles.php, config, or namespaces.
  • Don't build architectural dependencies on it. Inject factories via your own small service locator or static::getContainer() if you must; if the bundle disappears (or you vendor it), you don't want 300 tests tied to its compiler pass tags — or to a namespace that got renamed between point releases.
  • Upgrade path if you move to Foundry 2.x: Foundry's own bundle now handles a lot of service registration and auto_refresh_proxies; re-evaluate whether you need any of this at all. For most projects the correct answer is: use ZenstruckFoundryBundle alone, add ResetDatabase, and skip this package.
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.
socialdept/tenant-domains
tautvydasr/blade-class-names
socialdept/color-scales
maherelgamil/controller
coleus/widgets
coleus/table
coleus/users
coleus/music
coleus/health
coleus/calendar
coleus/notes
coleus/support
coleus/settings
coleus/apps
seampact/laravel
emmyconceptng/laravel-ng-postcode
jjsquady/round-robin
skyraptor/chatter
edlugz/sasapay
abbasudo/artisan-route