Environment‑specific bindings#
InterMix supports environment-aware service bindings – ideal for swapping real implementations with fakes, stubs, or vendors based on the current runtime environment.
Use‑Case 🎯#
In production, you want the real payment gateway.
In local/test, you prefer a dummy or fake.
Instead of writing custom conditionals in your app, bind per environment:
$c->options()
->bindInterfaceForEnv('prod', PaymentGateway::class, StripeGateway::class)
->bindInterfaceForEnv('test', PaymentGateway::class, FakeGateway::class);
Then activate the current env:
$c->options()->setEnvironment($_ENV['APP_ENV'] ?? 'prod');
How It Works Behind the Scenes#
When you resolve an interface like:
$gateway = $c->get(PaymentGateway::class);
The container internally checks:
Is
envmode active?Is there a matching
bindInterfaceForEnv()mapping for the current env?If yes, use the target class (e.g.
StripeGateway)Otherwise, fallback to global bindings or autowiring
This keeps your business logic decoupled from deployment configs.
Multiple Environments 📦#
You may bind different interfaces for different environments:
$c->options()
->bindInterfaceForEnv('local', LoggerInterface::class, FileLogger::class)
->bindInterfaceForEnv('prod', LoggerInterface::class, CloudLogger::class)
->bindInterfaceForEnv('debug', LoggerInterface::class, VerboseLogger::class);
Switch dynamically:
$c->options()->setEnvironment('debug');
Priority & Resolution Order#
If multiple environments are defined, InterMix only uses the one explicitly
set via Infocyph\InterMix\DI\Managers\OptionsManager::setEnvironment.
Resolution priority:
Environment-bound class (if active)
Globally bound class via
Infocyph\InterMix\DI\Managers\DefinitionManager::bindAutowire fallback (if
injection=true)
Best Practices 💡#
Use environment bindings for external systems (payment, mail, auth).
Avoid overusing for things easily toggled with config values.
Prefer strings like
"prod","test","local"– but any name is allowed.
You can also override definition metadata (lifetime/tags) per environment:
$c->definitions()
->bind('mailer', fn () => new Mailer(), tags: ['core']);
$c->options()
->setDefinitionMetaForEnv('test', 'mailer', LifetimeEnum::Transient, ['core', 'test-only'])
->setEnvironment('test');
Now mailer behaves as transient in test, while using default metadata in
other environments.
Next stop » Definition-level Caching