Services and lifetimes¶
A class is a service when it says how long it lives:
#[Singleton] final class PriceList { ... } // one per worker
#[Scoped] final class CurrentTenant { ... } // one per request, job or message
#[Transient] final class InvoiceNumber { ... } // new on every injection
Dependencies arrive through the constructor. There is no app(), no facade and no service locator.
Choosing a lifetime¶
Ask: does this object know anything about the current request? If yes, it is Scoped. If it holds a connection, a client or immutable data, it is a Singleton. If it is a small helper with no state, Transient.
The compiler rejects a Singleton that depends on a Scoped service, including through a Transient in between, because the singleton would keep the first request's object forever.
Interfaces¶
Bind an interface to an implementation in app.php:
->bind(PaymentGateway::class, StripeGateway::class)
->bindIn('test', PaymentGateway::class, FakeGateway::class)
Configuration values¶
/** @param list<string> $countries */
public function __construct(
#[Config('stripe.secret')] private string $secret,
#[Config('stripe.timeout_ms')] private int $timeoutMs = 3000,
#[Config('shipping.countries')] private array $countries = ['BE', 'NL'],
) {}
Strings, ints, floats, bools, list<string> (comma-separated from an env var works) and arrays are
supported. Types are checked when the service is built; keel inspect lists every key.
Many implementations¶
injects every registered service that is an instance of HealthCheck, resolved at build time.
Classes you do not own¶
Use a factory method on a service:
#[Singleton]
final readonly class SearchClients
{
public function __construct(#[Config('search.url')] private string $url) {}
#[Factory(Lifetime::Singleton)]
public function client(): \OpenSearch\Client
{
return \OpenSearch\ClientBuilder::fromConfig(['hosts' => [$this->url]]);
}
}
Cleaning up¶
Implement Keel\Container\Disposable. Scoped services are disposed when their scope closes (in reverse
creation order); singletons when the worker shuts down.