ioc-interop / interface
Interoperable IOC container interfaces for PHP.
Installs: 4
Dependents: 1
Suggesters: 0
Security: 0
Stars: 0
Watchers: 1
Forks: 1
Open Issues: 1
pkg:composer/ioc-interop/interface
Requires (Dev)
- pds/composer-script-names: ^1.0
- pds/skeleton: ^1.0
- phpstan/phpstan: ^2.0
This package is auto-updated.
Last update: 2026-01-06 04:18:18 UTC
README
This package provides interoperable interfaces for inversion-of-control (IOC) container functionality. It reflects, refines, and reconciles the common practices identified within several pre-existing projects.
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in BCP 14 (RFC 2119, RFC 8174).
Interfaces
This package defines the following interfaces:
-
IocContainer affords obtaining service instances by name, whether as shared instances or new unshared instances.
-
IocServices affords a registry of service instances, factories, and aliases.
-
IocProvider affords provision of service instances, factories, and aliases to an IocServices instance.
-
IocContainerFactory affords obtaining a new instance of IocContainer.
-
IocThrowable extends Throwable to mark an Exception as IOC-related.
-
IocTypeAliases defines PHPStan type aliases to aid static analysis.
IocContainer
The IocContainer interface affords obtaining service instances by name, whether as shared instances or new unshared instances.
-
Directives:
- Implementations MUST convert each
$serviceNameargument to its alias, if an alias exists for that$serviceName.
- Implementations MUST convert each
IocContainer Methods
-
public function hasService(ioc_service_name_string $serviceName) : bool;
- Is the container capable of returning a shared instance of the
$serviceName?
- Is the container capable of returning a shared instance of the
-
public function getService( ioc_service_name_string $serviceName, ) : ioc_service_object;
-
Returns a shared instance of the
$serviceName, instantiating it if necessary. -
Directives:
-
Implementations MUST throw IocThrowable if the container cannot return a shared instance of the
$serviceName. -
Implementations MUST return the same instance of the
$serviceNameservice each time this method is called.
-
-
Notes:
- Create and retain a new instance if necessary. In practice,
this likely means calling
newService($serviceName)and holding onto the newly-created instance for later calls togetService($serviceName).
- Create and retain a new instance if necessary. In practice,
this likely means calling
-
-
public function newService( ioc_service_name_string $serviceName, ) : ioc_service_object;
-
Returns a new instance of the
$serviceName. -
Directives:
-
Implementations MUST throw IocThrowable if the container cannot return a new instance of the
$serviceName. -
Implementations MUST return a different instance of the
$serviceNameeach time this method is called.
-
-
Notes:
- Service instantiation logic is not specified. Implementations might use autowiring, configuration, factories, or some other means to create the service instance. The creation logic might be part of the container, or it might be part of some other subsystem.
-
IocServices
The IocServices interface affords a registry of service instances, factories, and aliases.
-
Directives:
- Implementations MUST NOT convert any
$serviceNameargument to its alias.
- Implementations MUST NOT convert any
IocServices Methods
-
public function hasServiceInstance(ioc_service_name_string $serviceName) : bool;
- Has a shared instance of the
$serviceNamebeen set?
- Has a shared instance of the
-
public function getServiceInstance( ioc_service_name_string $serviceName, ) : ioc_service_object;
-
Returns the shared instance of the
$serviceName. -
Directives:
- Implementations MUST throw IocThrowable if a shared instance
of the
$serviceNameis not available.
- Implementations MUST throw IocThrowable if a shared instance
of the
-
-
public function setServiceInstance( ioc_service_name_string $serviceName, ioc_service_object $instance, ) : void;
- Sets the shared instance of the
$serviceName.
- Sets the shared instance of the
-
public function unsetServiceInstance( ioc_service_name_string $serviceName, ) : void;
- Unsets the shared instance of the
$serviceName.
- Unsets the shared instance of the
-
public function hasServiceFactory(ioc_service_name_string $serviceName) : bool;
- Has a factory for the
$serviceNamebeen set?
- Has a factory for the
-
public function getServiceFactory( ioc_service_name_string $serviceName, ) : ioc_service_factory_callable;
-
Returns the factory for the
$serviceName. -
Directives:
- Implementations MUST throw IocThrowable a factory for the
$serviceNameis not available.
- Implementations MUST throw IocThrowable a factory for the
-
-
public function setServiceFactory( ioc_service_name_string $serviceName, ioc_service_factory_callable $serviceFactory, ) : void;
-
Sets the factory for the
$serviceName. -
Notes:
- The
callabletype allows for a wide range of implementations. Cf. the https://php.net/callable documentation for more.
- The
-
-
public function unsetServiceFactory( ioc_service_name_string $serviceName, ) : void;
- Unsets the factory for the
$serviceName.
- Unsets the factory for the
-
public function hasServiceAlias(ioc_service_name_string $serviceName) : bool;
- Has an alias for the
$serviceNamebeen set?
- Has an alias for the
-
public function getServiceAlias( ioc_service_name_string $serviceName, ) : ioc_service_name_string;
-
Returns the alias for the
$serviceName. -
Directives:
- Implementations MUST throw IocThrowable an alias for the
$serviceNameis not available.
- Implementations MUST throw IocThrowable an alias for the
-
-
public function setServiceAlias( ioc_service_name_string $serviceName, ioc_service_name_string $serviceAlias, ) : void;
-
Sets the alias for one
$serviceNameto another service. -
Directives:
- Implementations MUST throw IocThrowable if the
$serviceAliasitself is aliased.
- Implementations MUST throw IocThrowable if the
-
Notes:
- Only one level of aliasing is allowed. An alias may not point to another alias; this is to prevent the possibillity of infinite recursion.
-
-
public function unsetServiceAlias(ioc_service_name_string $serviceName) : void;
- Unsets the alias for the
$serviceName.
- Unsets the alias for the
IocProvider
The IocProvider interface affords provision of service instances, factories, and aliases to an IocServices instance.
IocProvider Methods
-
public function provideServices(IocServices $services) : void;
-
Provides service instances, factories, and aliases to the
$services. -
Notes:
- Provision includes a wide range of activity. The implementation
can set, unset, replace, etc. the instances, factories, and aliases
in the
$services.
- Provision includes a wide range of activity. The implementation
can set, unset, replace, etc. the instances, factories, and aliases
in the
-
IocContainerFactory
The IocContainerFactory interface affords obtaining a new instance of IocContainer.
IocContainerFactory Methods
-
public function newContainer() : IocContainer;
-
Returns a new instance of IocContainer.
-
Notes:
- Container instantiation logic is not specified. Implementations might use providers, configuration files, attribute or annotation collection, or some other means to create and populate a container. Implementations might also choose to return a compiled or otherwise reconstituted container.
-
IocThrowable
The IocThrowable interface extends Throwable to mark an Exception as IOC-related. It adds no class members.
IocTypeAliases
The IocTypeAliases interface defines PHPStan type aliases to aid static analysis.
-
ioc_service_factory_callable callable(IocContainer):object- A
callableto create and return a new instance of a service.
- A
-
ioc_service_name_string class-string<T>|string- A
class-stringorstringname for a service.
- A
-
ioc_service_object ($serviceName is class-string<T> ? T : object)- The service
objectfor a given service name.
- The service
Implementations
-
Directives:
- Implementations MAY define additional class members not defined in these interfaces.
-
Notes:
- Reference implementations may be found at https://github.com/ioc-interop/impl.
Q & A
How is Ioc-Interop different from PSR-11?
PSR-11 is an earlier recommendation that offers an interface to get
items from a container, and to see if that container has a particular item.
The Ioc-Interop standard is more expansive.
-
Ioc-Interop offers separate interface methods for getting shared service instances and creating new service instances. PSR-11 defines only
get(), which may do either or both depending on the implementation. -
Ioc-Interop offers an interface to set/get/has/unset service instances, factories, and aliases. PSR-11 offers no such interface.
-
Ioc-Interop is intended to contain only services (
object). PSR-11 is intended to contain anything (mixed). -
Ioc-Interop offers a container factory. PSR-11 offers none.
-
Ioc-Interop defines only one Throwable interface; PSR-11 defines two exception interfaces.
Is Ioc-Interop compatible with PSR-11?
No, in the sense that the method names, signatures, and intents are different.
Yes, in the sense that both may be implemented on the same class; the method names are different, and so are non-conflicting.
Is IocContainer a Dependency Injection system or a Service Locator?
IocContainer acts a Service Locator only when it is used as a dependency in order to retrieve other dependencies from it.
Why does IocContainer define newService() instead of make(), create(), or build() ?
The researched projects use several different terms to indicate that a new
service instance will be returned: build (2 projects), create (3), get (6),
make (3), and new (2).
The terms get and make are ambiguous in the researched projects. They might:
-
create a new service instance every time;
-
return a shared service instance every time;
-
create a new service instance the first time and return that same instance every time thereafter; or,
-
do some combination of the above, depending how the service was defined.
The terms build and create are less-ambiguous, but are much less common.
In comparison, newService() is easily disambiguated from getService().
Ioc-Interop stipulates that former always returns a new instance, and the latter
always returns a shared instance (after creating it if necessary).
Why is IocContainer separate from IocServices?
Whereas IocContainer is for obtaining instances, IocServices is for registering the instances, factories, and aliases involved in producing the services to be obtained.
This separation allows for containers that are fully "open" by implementing both interfaces on the same class, and for containers that are "closed" in the sense that the services are encapsulated but not publicly modifiable.
Why IocContainer "Factory" and not IocContainer "Builder" ?
"Builder" implies calling public setup methods, then a build method. "Factory"
implies only a new method. Even if there are multiple steps to the factory
process, they are not accessible as public methods.
Why does IocProvider define provideServices() instead of register() ?
The method name register() is by far the majority choice for service provider
implementations. This standard breaks with that choice for consistency reasons.
Ioc-Interop opines that, unless the result is outright barbarous,
interface names and method names should mimic each other. Given a Provider
interface, its methods should provide(); given a register() method, its
interface should be a Registrant. Further, as with the other interfaces herein,
the word "service" should be incorporated into the method name. This leaves two
choices:
IocProvider::provideServices()(closer to the majority class name)IocRegistrant::registerServices()(closer to the majority method name)
Ioc-Interop opts in favor of honoring the class name, and modeling the method name after it.