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

1.x-dev 2026-01-06 04:18 UTC

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

The IocContainer interface affords obtaining service instances by name, whether as shared instances or new unshared instances.

  • Directives:

    • Implementations MUST convert each $serviceName argument to its alias, if an alias exists for that $serviceName.

IocContainer Methods

  • public function hasService(ioc_service_name_string $serviceName) : bool;
    • Is the container capable of returning a shared instance of the $serviceName?
  • 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 $serviceName service 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 to getService($serviceName).
  • 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 $serviceName each 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 $serviceName argument to its alias.

IocServices Methods

  • public function hasServiceInstance(ioc_service_name_string $serviceName) : bool;
    • Has a shared instance of the $serviceName been set?
  • 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 $serviceName is not available.
  • public function setServiceInstance(
        ioc_service_name_string $serviceName,
        ioc_service_object $instance,
    ) : void;
    • Sets the shared instance of the $serviceName.
  • public function unsetServiceInstance(
        ioc_service_name_string $serviceName,
    ) : void;
    • Unsets the shared instance of the $serviceName.
  • public function hasServiceFactory(ioc_service_name_string $serviceName) : bool;
    • Has a factory for the $serviceName been set?
  • 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 $serviceName is not available.
  • public function setServiceFactory(
        ioc_service_name_string $serviceName,
        ioc_service_factory_callable $serviceFactory,
    ) : void;
    • Sets the factory for the $serviceName.

    • Notes:

      • The callable type allows for a wide range of implementations. Cf. the https://php.net/callable documentation for more.
  • public function unsetServiceFactory(
        ioc_service_name_string $serviceName,
    ) : void;
    • Unsets the factory for the $serviceName.
  • public function hasServiceAlias(ioc_service_name_string $serviceName) : bool;
    • Has an alias for the $serviceName been set?
  • 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 $serviceName is not available.
  • public function setServiceAlias(
        ioc_service_name_string $serviceName,
        ioc_service_name_string $serviceAlias,
    ) : void;
    • Sets the alias for one $serviceName to another service.

    • Directives:

      • Implementations MUST throw IocThrowable if the $serviceAlias itself is aliased.
    • 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.

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.

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 callable to create and return a new instance of a service.
  • ioc_service_name_string class-string<T>|string
    
    • A class-string or string name for a service.
  • ioc_service_object ($serviceName is class-string<T> ? T : object)
    
    • The service object for a given service name.

Implementations

  • Directives:

    • Implementations MAY define additional class members not defined in these interfaces.
  • Notes:

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.