VOOZH about

URL: https://deepwiki.com/hypervel/container/4.1-method-invocation-and-dependency-injection

⇱ Method Invocation & Dependency Injection | hypervel/container | DeepWiki


Loading...
Menu

Method Invocation & Dependency Injection

Purpose and Scope

This page documents the BoundMethod system, which provides automatic dependency injection for method and function invocation. The BoundMethod class serves as a static utility that allows the container to call any callable (closure, method, function) while automatically resolving and injecting its dependencies.

For information about how dependencies are resolved during service instantiation, see Dependency Resolution. For lifecycle callbacks that execute during resolution, see Lifecycle Callbacks. For binding custom method implementations, see Extenders, Aliases & Method Bindings.


Overview

The BoundMethod class is a static utility located at src/BoundMethod.php15 that acts as the method invocation engine for the container. It enables the container's call() method to invoke any callable with automatic parameter resolution and dependency injection.

Sources: src/BoundMethod.php1-223


Supported Callable Formats

The BoundMethod::call() method accepts multiple callable formats, making it flexible for various invocation patterns. The system intelligently detects the callable type and routes it to the appropriate handler.

Callable Format Table

FormatExampleDetection LogicHandler Method
Class@method string'App\Service@handle'Contains @ signcallClass() 125-144
Closurefunction($dep) { }instanceof ClosureDirect invocation 37-40
Array callable[$object, 'method']is_array()callBoundMethod() 54-63
Static method'Class::method'Contains ::Converted to array 48-50
Invokable objectnew InvokableClass()Has __invokeConverted to array 43-45

Sources: src/BoundMethod.php25-74


Call Flow and Routing

The following diagram illustrates how BoundMethod::call() routes different callable formats through the system:


Diagram: Call Routing Logic in BoundMethod::call()

Sources: src/BoundMethod.php25-74 src/BoundMethod.php125-144 src/BoundMethod.php152-168


Dependency Resolution Mechanism

The dependency resolution process involves collecting parameter definitions and resolving each parameter through a priority-based system. Two collector interfaces are used depending on the callable type:

Collector Interfaces

Collector InterfacePurposeUsed ForMethod Called
MethodDefinitionCollectorInterfaceCollects method parameter definitionsClass methodsgetParameters($class, $method) 194-195
ClosureDefinitionCollectorInterfaceCollects closure parameter definitionsClosuresgetParameters($closure) 207-208

Both collectors return an array of parameter definition objects that contain metadata about each parameter.

Sources: src/BoundMethod.php9-10 src/BoundMethod.php192-211

Parameter Definition Metadata

Each parameter definition object provides the following metadata through the getMeta() method:

  • name: The parameter variable name
  • defaultValueAvailable: Whether a default value exists 94
  • defaultValue: The default value if available 95

Additional methods on the definition object:

  • getName(): Returns the type hint (class/interface name) 88-89
  • allowsNull(): Whether the parameter accepts null 98

Sources: src/BoundMethod.php76-115


Parameter Resolution Priority

The getDependencyParameters() method 76-115 implements a sophisticated priority system for resolving method parameters. This diagram shows the resolution order:


Diagram: Parameter Resolution Priority in getDependencyParameters()

Priority Order

  1. Named parameter match ($parameters[$paramName]) 82-84
  2. Index-based match ($parameters[$index]) 85-87
  3. Type-based match ($parameters[$typeName]) 88-90
  4. Default value (if defined) 94-95
  5. Container resolution (if type registered) 96-97
  6. Null (if parameter is nullable) 98-99
  7. Exception (if none of the above) 105

Values found in the $parameters array are normalized through NormalizerInterface::denormalize() 108 which handles type conversion and validation.

Sources: src/BoundMethod.php76-115


Method Bindings

Method bindings provide a way to override the default invocation behavior for specific class methods. When a method binding exists, the container calls the custom binding instead of the actual method.

Method Binding Flow


Diagram: Method Binding Resolution Flow

The normalizeMethod() helper 180-185 converts array callables to the Class@method string format used as the method binding key. The container's hasMethodBinding() and callMethodBinding() methods (documented in Extenders, Aliases & Method Bindings) handle the actual binding logic.

Sources: src/BoundMethod.php152-168 src/BoundMethod.php180-185


Integration with Container

The BoundMethod class requires a ContainerContract instance and delegates several operations to container services:

Container Service Dependencies


Diagram: BoundMethod Integration with Container Services

Service Resolution Points

ServiceResolution PointPurpose
MethodDefinitionCollectorInterface194Retrieve method parameter definitions
ClosureDefinitionCollectorInterface207Retrieve closure parameter definitions
NormalizerInterface108Convert and validate parameter values
Target class instance141Resolve the class for Class@method syntax
Dependency types97Resolve type-hinted dependencies

Sources: src/BoundMethod.php8-11 src/BoundMethod.php194-195 src/BoundMethod.php207-208 src/BoundMethod.php108 src/BoundMethod.php141


Class@method Syntax

The Class@method syntax ('App\Service@handle') provides a string-based way to specify method calls. This is particularly useful in configuration files and routing definitions.

Parsing and Execution

The callClass() method 125-144 handles this syntax:

  1. Parse: Split the string on @ delimiter 127
  2. Extract: First segment is class name, second is method name 132-133
  3. Fallback: Use $defaultMethod if no @ present 132-133
  4. Resolve: Get class instance from container 141
  5. Recurse: Call BoundMethod::call() with array callable 139-143

Example Flow:

Input: 'App\Service@handle'
 ↓
Segments: ['App\Service', 'handle']
 ↓
Resolve: $container->get('App\Service')
 ↓
Convert: [$serviceInstance, 'handle']
 ↓
Recursive Call: BoundMethod::call($container, [$serviceInstance, 'handle'], $parameters)

Sources: src/BoundMethod.php125-144


Error Handling

The BoundMethod class throws BindingResolutionException in two scenarios:

Exception Scenarios

ScenarioThrown AtConditionMessage Format
Invalid callable73Callable is not recognized format"Invalid callable {$callableName} provided."
Missing method name136Class@method has no method and no default"Method not provided."
Unresolvable parameter105Required parameter cannot be resolved"Unable to resolve dependency [Parameter #{$index} [ <required> ${$name} ]] in class {$class}"

Invalid Callable Detection

The system validates callables by checking against all supported formats 27-64 If none match, it constructs a descriptive error message using:

  • Object class name 68
  • String representation 70
  • Fallback to "Unknown" 66

Sources: src/BoundMethod.php66-73 src/BoundMethod.php101-105 src/BoundMethod.php136


Usage from Container

While BoundMethod can be invoked directly as a static utility, it is typically accessed through the container's call() method, which wraps BoundMethod::call() with the container instance:


The container's implementation of call() is documented in the API reference (see API Reference).

Sources: src/BoundMethod.php25-74