Container class
The Container class is the registry of services used by your application. It stores object instances, resolves them by type, and can defer creation until first use.
It implements Psr\Container\ContainerInterface, so it can also be passed to code that expects a PSR-11 compatible container.
Constructing a container
use GT\ServiceContainer\Container;
$container = new Container();
In normal application code, the constructor does not need any arguments.
An optional Injector can be supplied, which is mainly useful when composing advanced setups or tests:
use GT\ServiceContainer\Container;
use GT\ServiceContainer\Injector;
$baseContainer = new Container();
$injector = new Injector($baseContainer);
$container = new Container($injector);
Without any arguments, a default Injector is used. In practice, most projects should just use the no-argument form.
Setting services
Use set() to store one or more object instances:
$container->set(
new Greeter(),
new DateTimeImmutable(),
);
Only objects may be registered this way. Scalars, arrays, and null are rejected with a ServiceContainerException.
Getting services
Use get() with a class name:
$greeter = $container->get(Greeter::class);
If the service has not been registered and there is no loader for it, a ServiceNotFoundException is thrown.
Checking if a service exists
Use has() when you need to test availability first:
if($container->has(Greeter::class)) {
$greeter = $container->get(Greeter::class);
}
has() and get() are both case-insensitive.
Interface and parent class resolution
When an object is registered, the container also exposes it through its interfaces and parent classes.
interface GreetingInterface {
public function greet():string;
}
class Greeter implements GreetingInterface {
public function greet():string {
return "Hello!";
}
}
$container->set(new Greeter());
$greeting = $container->get(GreetingInterface::class);
This makes the library useful in applications that depend on abstractions instead of concrete classes.
One service per type
The container keeps a single value for each class or interface name. Registering another object of the same type replaces the previous one for that key.
This library does not try to manage multiple named services of the same type. If you need that, create a higher-level application object that exposes the variation you need.
When service construction should be deferred until first use, use Lazy loaders.