VOOZH about

URL: https://deepwiki.com/hypervel/container/3.4-dependency-resolution

⇱ Dependency Resolution | hypervel/container | DeepWiki


Loading...
Menu

Dependency Resolution

Purpose and Scope

This document explains how the Hypervel Container resolves dependencies when requesting services. It covers the resolution methods (make() and get()), the multi-stage resolution pipeline, alias resolution, callback hooks, and how instances are created and cached.

For information about registering services in the container, see Service Binding. For method invocation with dependency injection, see Method Invocation & Dependency Injection. For lifecycle callbacks registration, see Lifecycle Callbacks.

Resolution Methods

The container provides two primary methods for resolving dependencies: make() and get().

The make() Method

The make() method builds an entry from the container by its name, resolving it fresh each time it is called. This makes the container behave like a factory for the requested service.

make(string $name, array $parameters = []): mixed

Parameters:

  • $name - The entry name or class name to resolve
  • $parameters - Optional parameters to inject, overriding automatic resolution

The method performs the following operations:

  1. Resolves any aliases to their concrete bindings
  2. Fires "before resolving" callbacks
  3. Delegates to parent Hyperf container for actual instantiation
  4. Applies any registered extenders to the result
  5. Fires "resolving" and "after resolving" callbacks

Sources: src/Container.php109-132

The get() Method

The get() method finds an entry of the container by its identifier and returns it. For singleton bindings, this returns the cached instance if it has been resolved previously. For factory bindings, it creates a new instance.

get(string $id): mixed

Parameters:

  • $id - The identifier of the entry to look for

The method resolves aliases and delegates to the parent Hyperf container, which handles caching logic for singleton bindings.

Sources: src/Container.php139-146

Differences Between make() and get()

Aspectmake()get()
PurposeFactory-style resolutionStandard PSR-11 resolution
ParametersSupports custom parametersNo parameters
CachingBypasses cache, always creates newRespects singleton cache
CallbacksFires full callback pipelineFires callbacks on first resolution only
ExtendersApplied on every callApplied on first resolution only

Sources: src/Container.php109-146

The Resolution Pipeline

The container implements a sophisticated multi-stage resolution pipeline that provides hooks for cross-cutting concerns.

Resolution Pipeline Flow


Sources: src/Container.php109-132 src/Container.php522-578

Pipeline Stages

Stage 1: Alias Resolution

Before any resolution occurs, the container checks if the requested name is an alias and resolves it to the concrete binding name.

Sources: src/Container.php111-113

Stage 2: Before Resolving Callbacks

The container fires "before resolving" callbacks, allowing hooks to register additional bindings or modify the resolution context before instantiation occurs.

Sources: src/Container.php118 src/Container.php522-531

Stage 3: Hyperf Resolution

The actual instance creation is delegated to the parent Hyperf container, which handles:

  • Checking the resolved entries cache for singletons
  • Autowiring constructor dependencies
  • Injecting dependencies recursively
  • Caching the result if configured as a singleton

Sources: src/Container.php120

Stage 4: Extender Application

After the instance is created, any registered extenders are applied in sequence. Extenders are closures that can wrap, modify, or replace the resolved instance.

Sources: src/Container.php125-127

Stage 5: Resolving and After Resolving Callbacks

The container fires both "resolving" and "after resolving" callbacks, providing hooks for logging, event broadcasting, or other post-resolution operations.

Sources: src/Container.php129 src/Container.php552-578

Alias Resolution

The container supports aliasing, allowing multiple names to resolve to the same concrete binding. Alias resolution is recursive, following the alias chain until reaching the concrete binding.

Alias Resolution Algorithm


The getAlias() method recursively follows the alias chain:

public function getAlias(string $abstract): string
{
 return isset($this->aliases[$abstract])
 ? $this->getAlias($this->aliases[$abstract])
 : $abstract;
}

All resolution methods (make(), get(), set(), unbind()) perform alias resolution before processing, ensuring consistent behavior regardless of which name is used to request the service.

Sources: src/Container.php622-627 src/Container.php111-113 src/Container.php141-143

Autowiring and Constructor Injection

The container inherits autowiring capabilities from the Hyperf DI container. When resolving a class that hasn't been explicitly bound, the container automatically:

  1. Inspects the class constructor using reflection
  2. Resolves each constructor parameter by type hint
  3. Recursively resolves dependencies of dependencies
  4. Instantiates the class with all dependencies injected

This process is handled by the parent HyperfContainer::make() method that Hypervel delegates to during the resolution pipeline.

Example Resolution Chain:

class DatabaseConnection {
 public function __construct(ConfigRepository $config) { }
}

class UserRepository {
 public function __construct(DatabaseConnection $db) { }
}

// When resolving UserRepository:
// 1. Container inspects UserRepository constructor
// 2. Sees DatabaseConnection dependency
// 3. Recursively resolves DatabaseConnection
// 4. Resolves ConfigRepository for DatabaseConnection
// 5. Instantiates everything in reverse order

For classes with primitive parameters or complex resolution requirements, use the $parameters argument of make() or register a binding with a factory closure.

Sources: src/Container.php120

Resolution Callbacks

The container provides three distinct callback stages that fire during the resolution process. Callbacks can be registered globally (for all resolutions) or for specific types.

Callback Registration Methods

MethodPurposeArguments Received
beforeResolving()Before instance creation($abstract, $parameters, $container)
resolving()During instance creation($object, $container)
afterResolving()After instance creation($object, $container)

Before Resolving Callbacks

These callbacks fire before the container attempts to create an instance. They receive the abstract name and parameters, allowing modification of the resolution context.

Registration:


Sources: src/Container.php467-478 src/Container.php522-531

Resolving Callbacks

These callbacks fire after the instance is created and extenders are applied, but before after-resolving callbacks. They receive the resolved object.

Registration:


Sources: src/Container.php485-496 src/Container.php552-562

After Resolving Callbacks

These callbacks fire as the final stage of resolution, after all other processing is complete. They also receive the resolved object.

Registration:


Sources: src/Container.php503-514 src/Container.php570-578

Callback Execution Order


Sources: src/Container.php109-132

Type-Specific Callback Matching

Type-specific callbacks support inheritance matching. A callback registered for a parent class or interface will fire when resolving any subclass or implementation:


The matching logic checks both exact type matches and instanceof relationships.

Sources: src/Container.php586-597

Extenders

Extenders allow modification of resolved instances after creation but before callbacks fire. They are closures that receive the instance and container, returning a potentially modified instance.

Registering Extenders

extend(string $abstract, Closure $closure): void

The closure receives two parameters:

  • $service - The resolved instance
  • $container - The container instance

Example usage:


Extender Application

Multiple extenders can be registered for the same abstract. They are applied sequentially in registration order, with each extender receiving the result of the previous one:


Sources: src/Container.php314-324 src/Container.php632-635

Extenders for Already-Resolved Services

When calling extend() on an already-resolved singleton, the container immediately applies the extender to the cached instance and fires rebound callbacks:


Sources: src/Container.php318-321

Resolution State Management

The container tracks which services have been resolved and maintains a cache of singleton instances.

Checking Resolution State

The resolved() method determines whether an abstract has been resolved at least once:

resolved(string $abstract): bool

This checks the $resolvedEntries array, which tracks all services that have been instantiated. The method resolves aliases before checking:


Sources: src/Container.php219-226

Instance Caching

The parent Hyperf container manages instance caching based on binding configuration:

  • Singleton bindings: Cached in $resolvedEntries after first resolution
  • Factory bindings: Created fresh on every make() call
  • Instance bindings: Stored immediately in $resolvedEntries

The get() method always checks the cache first, while make() bypasses the cache check but still stores singletons after creation.

Managing the Instance Cache

The container provides methods to manipulate the instance cache:

MethodPurpose
forgetInstance(string $abstract)Remove a specific instance from cache
forgetInstances()Clear all cached instances
flush()Clear instances, aliases, and bindings

Sources: src/Container.php656-677

Resolution State Diagram


Sources: src/Container.php219-226 src/Container.php656-667

Resolution with Custom Parameters

The make() method accepts a $parameters array that overrides automatic dependency resolution for specific parameters. This is useful for runtime values that cannot be autowired:


The parameters are passed to the Hyperf resolution logic, which merges them with autowired dependencies based on parameter names or positions.

Sources: src/Container.php109-132


Summary: Dependency resolution in the Hypervel Container follows a sophisticated pipeline that combines alias resolution, callback hooks, Hyperf's autowiring, extenders, and instance caching. The make() and get() methods provide different resolution strategies, while the callback system enables cross-cutting concerns without tight coupling. The container's state management tracks resolved instances and supports cache manipulation for testing and dynamic reconfiguration.

Refresh this wiki

On this page