Services
A service is any object the container knows how to construct for you. Whether the container was compiled from a .ctn file, built with the ContainerBuilder or wired up dynamically at runtime, the API for resolving services is always the same.
Shared vs. factory services
Every service is resolved in one of two ways:
- Shared (the default) — the service is constructed once, cached, and the very same instance is returned on every subsequent
get. This is the singleton behaviour most services want. - Factory (prototype) — a fresh instance is constructed on every
get.
How a service becomes shared or not is a matter of binding it, which is covered in Service Binding. This page is about resolving and managing services that already exist.
Getting a service
Retrieves the service with the given name. If the service is shared and has not been requested before, it is constructed now and cached; factory services are constructed fresh every time.
$container->get('repository.comment');The name container is reserved and always refers to the container itself:
$container->get('container'); // === $containerRequesting a service that does not exist throws an UnknownServiceException. Either guard the call with has() or catch the exception if you don't fully trust your dependency tree.
try {
$container->get('not.sure.if.exists');
} catch (\ClanCats\Container\Exceptions\UnknownServiceException $e) {
// it's not there
}Retrieve a service from the container.
Method definition:
public function get(string $serviceName)Arguments
| Data type | Variable name | Comment |
|---|---|---|
| string | $serviceName | The name / Identifier of the service to look for. |
Returns
mixed The requested service.
Checking if a service exists
if ($container->has('not.sure.if.exists')) {
$container->get('not.sure.if.exists');
}Does the container have the given service?
Method definition:
public function has(string $serviceName) : boolArguments
| Data type | Variable name | Comment |
|---|---|---|
| string | $serviceName | The name / Identifier of the service to look for. |
Returns
bool
Listing available services
Useful when building debugging tooling — returns the names of every service the container can resolve.
echo implode(', ', $container->available());Returns an array of all available service keys.
Method definition:
public function available() : arrayArguments
This method takes no arguments.
Returns
array<string>
Checking if a service is resolved
Tells you whether a service has already been constructed / requested. Mainly handy for profiling and debugging.
foreach ($container->available() as $serviceName) {
echo "@{$serviceName}: " . ($container->isResolved($serviceName) ? 'yes' : 'no') . PHP_EOL;
}Check if the given service has already been resolved / shared / initiated. A factory service will always return false.
Method definition:
public function isResolved(string $serviceName) : boolArguments
| Data type | Variable name | Comment |
|---|---|---|
| string | $serviceName | The name / Identifier of the service to look for. |
Returns
bool
Looking up services by metadata (tags)
Services can carry arbitrary metadata declared in a .ctn file with the = prefix (see Metadata & Tags). At runtime you collect them by key — this is how you gather, for example, every controller that declared a route without listing them by hand.
serviceNamesWithMetaData() returns a map of service name to that service's entries for the given key:
foreach ($container->serviceNamesWithMetaData('route') as $serviceName => $entries) {
$controller = $container->get($serviceName);
foreach ($entries as $route) {
// $route is one `= route: ...` entry, e.g. [['GET', 'POST'], '/signin']
$router->add($route[0], $route[1], $controller);
}
}Get an array of service names that have metadata with the given key
Method definition:
public function serviceNamesWithMetaData(string $key) : arrayArguments
| Data type | Variable name | Comment |
|---|---|---|
| string | $key | The metadata key |
Returns
array<string, array<mixed>>
You can also read the metadata of a single service, or list which keys it carries:
$container->getMetaData('controller.auth.sign_in', 'route'); // the 'route' entries
$container->getMetaDataKeys('controller.auth.sign_in'); // e.g. ['route', 'tag']Get the metadata of a specific service
Method definition:
public function getMetaData(string $serviceName, string $key) : arrayArguments
| Data type | Variable name | Comment |
|---|---|---|
| string | $serviceName |
Returns
array<string, array<mixed>>
Get the metadata keys of the given service
Method definition:
public function getMetaDataKeys(string $serviceName) : arrayArguments
| Data type | Variable name | Comment |
|---|---|---|
| string | $serviceName |
Returns
array<string>
Injecting an existing instance
When you already have an object and simply want to hand it to the container, use set. This stores the instance directly and overwrites anything shared under the same name.
$thing = new Thing();
$container->set('thing', $thing);Sets a value on the container instance. This will overwrite any service stored / shared under the same name.
Method definition:
public function set(string $serviceName, $serviceValue)Arguments
| Data type | Variable name | Comment |
|---|---|---|
| string | $serviceName | The name / Identifier of the service to look for. |
| mixed | $serviceValue |
Returns
void
TIP
To register a service definition (so the container constructs it lazily on demand) rather than a ready-made instance, use bind. See Service Binding.
Releasing a service
Removes the shared instance stored in the container without touching the service definition — the next get will construct a fresh one. Keep in mind PHP objects are reference counted, so an instance you still hold a reference to elsewhere is not actually destroyed.
$container->release('db.connection');Release a shared resolved service from the container. This will force the service to reload when accessed again.
Method definition:
public function release(string $serviceName) : boolArguments
| Data type | Variable name | Comment |
|---|---|---|
| string | $serviceName |
Returns
bool Return false on failure.
Removing a service
Releases the resolved instance (if any) and removes the service definition entirely.
$container->remove('kernel');TIP
This also works for compiled service definitions.
Removes a service from the container and releases the shared instance if it has been loaded.
Method definition:
public function remove(string $serviceName) : boolArguments
| Data type | Variable name | Comment |
|---|---|---|
| string | $serviceName | The name / Identifier of the service to look for. |
Returns
bool Returns true if the service has been removed.
