Configuration
Everything you need to configure the Wirebox container.
Table of contents
ContainerBuilder
The ContainerBuilder is the main entry point for configuring the container:
use AsceticSoft\Wirebox\ContainerBuilder;
$builder = new ContainerBuilder(projectDir: __DIR__);
The projectDir parameter is used as the base path for resolving .env files.
Directory Scanning
Scan one or more directories to auto-register all concrete classes. Abstract classes, interfaces, traits, and enums are automatically skipped:
$builder->scan(__DIR__ . '/src');
$builder->scan(__DIR__ . '/modules');
The scanner uses PHP’s tokenizer for fast, reliable class discovery without loading any files.
Excluding Files
Exclude files by glob pattern. Patterns are relative to the scanned directory:
$builder->exclude('Entity/*');
$builder->exclude('*Test.php');
$builder->scan(__DIR__ . '/src');
Call exclude() before scan() — exclusion patterns apply to subsequent scans.
You can also exclude individual classes with the #[Exclude] attribute:
use AsceticSoft\Wirebox\Attribute\Exclude;
#[Exclude]
class InternalHelper
{
// Will not be registered in the container
}
Auto-binding Interfaces
During scanning, if an interface has exactly one implementation in the scanned directories, Wirebox automatically binds the interface to that implementation.
If two or more implementations are found, the binding becomes ambiguous and build() will throw a ContainerException. Resolve ambiguity with an explicit bind():
$builder->scan(__DIR__ . '/Services');
// PaymentInterface has StripePayment and PayPalPayment — ambiguous!
$builder->bind(PaymentInterface::class, StripePayment::class);
Interfaces marked with #[AutoconfigureTag] are excluded from the ambiguous binding check, since multiple implementations are expected. See Autoconfiguration.
Interface Binding
Explicitly bind an interface (or abstract class) to a concrete implementation:
$builder->bind(LoggerInterface::class, FileLogger::class);
$builder->bind(CacheInterface::class, RedisCache::class);
When resolving a type-hinted dependency, the container checks bindings first, then falls back to concrete class resolution.
Factory Registration
Register a service with a custom factory closure for complex instantiation logic:
use AsceticSoft\Wirebox\Container;
$builder->register(PDO::class, function (Container $c) {
return new PDO(
sprintf('mysql:host=%s;port=%d;dbname=app',
$c->getParameter('db.host'),
$c->getParameter('db.port'),
),
);
});
The closure receives the Container instance, so you can resolve other services and parameters inside the factory.
Factory closures are not supported in compiled containers — they require runtime evaluation. Use autowiring with #[Param] or #[Inject] attributes where possible.
Fluent Definition API
register() returns a Definition object with a fluent interface for fine-grained control:
$builder->register(FileLogger::class)
->transient() // New instance every time
->lazy() // Deferred instantiation
->tag('logger') // Add a tag
->call('setFormatter', [JsonFormatter::class]); // Setter injection
Available Methods
| Method | Description |
|---|---|
singleton() |
One instance per container (default) |
transient() |
New instance on every get() call |
lazy() |
Return a proxy; real instance created on first access |
eager() |
Always create immediately (opt out of default lazy) |
tag(string ...$tags) |
Add one or more tags for grouped retrieval |
call(string $method, array $args) |
Configure setter injection (called after construction) |
Setter Injection
Configure methods to be called after the service is constructed:
$builder->register(Mailer::class)
->call('setTransport', [SmtpTransport::class])
->call('setLogger', [FileLogger::class]);
Arguments can be:
- Class names — resolved from the container
- Scalar values — passed as-is
Parameters
Define parameters that can reference environment variables:
$builder->parameter('db.host', '%env(DB_HOST)%');
$builder->parameter('db.port', '%env(int:DB_PORT)%');
$builder->parameter('app.debug', '%env(bool:APP_DEBUG)%');
$builder->parameter('rate.limit', '%env(float:RATE_LIMIT)%');
Type Casting
Supported casts inside %env(...)% expressions:
| Cast | Example | Result |
|---|---|---|
string (default) |
%env(DB_HOST)% |
"localhost" |
int |
%env(int:DB_PORT)% |
5432 |
float |
%env(float:RATE_LIMIT)% |
1.5 |
bool |
%env(bool:APP_DEBUG)% |
true |
Embedded Expressions
Environment expressions can be embedded in larger strings:
$builder->parameter('dsn', 'mysql:host=%env(DB_HOST)%;port=%env(DB_PORT)%');
// Result: "mysql:host=localhost;port=5432"
Plain Values
Parameters can also be plain values without env expressions:
$builder->parameter('pagination.limit', 25);
$builder->parameter('app.name', 'My Application');
Default Lazy Mode
By default, ContainerBuilder enables lazy mode — all services are created as lazy proxies unless they have an explicit #[Eager] attribute. This is generally what you want for performance.
To disable default lazy mode:
$builder->defaultLazy(false);
When disabled, services are created eagerly unless explicitly marked with #[Lazy].
See Lazy Proxies for details.
Building the Container
After configuration, call build() to create the runtime container:
$container = $builder->build();
The build() method:
- Applies default lazy mode to definitions without explicit settings
- Detects unsafe circular dependencies
- Creates and returns a
Containerinstance
build() validates the configuration and throws exceptions for issues like ambiguous bindings or unsafe circular dependencies. Fix these before deploying.
Next Steps
- Attributes — Declarative configuration with PHP attributes
- Environment Variables — Dotenv support and priority levels
- Compiled Container — Production optimization
- Advanced Features — Autoconfiguration, tags, lazy proxies