VOOZH about

URL: https://deepwiki.com/hypervel/http-client/10.4-runtime-extension-with-macros

⇱ Runtime Extension with Macros | hypervel/http-client | DeepWiki


Loading...
Menu

Runtime Extension with Macros

This document explains the macro system that enables runtime extension of the HTTP client's core classes. The Macroable trait from the Hyperf framework allows developers to dynamically add custom methods to Factory, PendingRequest, Request, Response, and ResponseSequence classes without modifying their source code.

For information about middleware extension, see Middleware and Handler Stack. For testing utilities provided by the Factory, see Testing and Mocking.


Overview

The HTTP client leverages the Hyperf\Macroable\Macroable trait to provide runtime extensibility across five core classes. This allows application developers to add domain-specific methods that integrate seamlessly with the fluent API.

Classes Supporting Macros

ClassPurposeMacro Use Cases
FactoryRequest creation and testingCustom client configurations, shortcuts for common request patterns
PendingRequestRequest configuration and executionCustom authentication schemes, domain-specific headers, specialized request types
RequestRequest data accessCustom data extraction, validation helpers
ResponseResponse data handlingCustom parsing methods, domain-specific data transformers
ResponseSequenceTest response sequencingCustom sequence builders, domain-specific test helpers

Sources: src/Factory.php34-36 src/PendingRequest.php40-41 src/Request.php16 src/Response.php27-29 src/ResponseSequence.php14


Macro Architecture

The following diagram illustrates how the Macroable trait integrates into the class hierarchy and method resolution flow:


Sources: src/Factory.php34-36 src/PendingRequest.php40-41 src/Response.php27-29


Adding Macros

Macros are registered statically on the target class using the macro() method. Each macro is a closure that receives the class instance as its context ($this).

Basic Macro Registration


Mixin Support

The Macroable trait also supports mixins, which allow registering multiple macros from a class at once:


Sources: Macroable trait functionality (from Hyperf framework dependency)


Method Resolution Flow

The following diagram shows how method calls are resolved when macros are present:


Sources: src/Factory.php518-525 src/Response.php495-500


Macro Resolution Priority

Different classes handle method resolution with distinct priorities:

Factory Class

src/Factory.php518-525

1. Check if native method exists (via Macroable trait)
2. Check if macro is registered → Execute macro
3. Fallback: Create new PendingRequest and proxy method call

The Factory's __call implementation:

  • First checks for registered macros via static::hasMacro($method)
  • If macro found, executes it via $this->macroCall($method, $parameters)
  • Otherwise, creates a PendingRequest and forwards the call: $this->createPendingRequest()->{$method}(...$parameters)

Response Class

src/Response.php495-500

1. Check if native method exists (via Macroable trait)
2. Check if macro is registered → Execute macro
3. Fallback: Proxy to underlying PSR-7 ResponseInterface

The Response's __call implementation:

  • Checks for macros via static::hasMacro($method)
  • If found, executes via $this->macroCall($method, $parameters)
  • Otherwise, proxies to the PSR-7 response: $this->response->{$method}(...$parameters)

PendingRequest, Request, and ResponseSequence

src/PendingRequest.php40-41 src/Request.php16 src/ResponseSequence.php14

1. Check if native method exists (via Macroable trait)
2. Check if macro is registered → Execute macro
3. No fallback: Throw BadMethodCallException

These classes use the Macroable trait without custom __call implementations, so undefined methods throw exceptions.

Sources: src/Factory.php518-525 src/Response.php495-500 src/PendingRequest.php40-41


Integration Points

Factory Macros and PendingRequest Creation

When a macro is called on the Factory, it can return a configured PendingRequest instance, integrating with the request lifecycle:


Example implementation:


Sources: src/Factory.php404-417 (createPendingRequest and newPendingRequest methods)


Common Macro Patterns

Pattern 1: Authentication Shortcuts

Add macros for custom authentication schemes:


Sources: src/PendingRequest.php390-397 (withToken method for reference)

Pattern 2: Response Data Transformers

Add domain-specific data extraction methods:


Sources: src/Response.php69-80 (json method)

Pattern 3: Request Validation

Add macros that perform validation before sending requests:


Sources: src/PendingRequest.php554-561 (beforeSending method)

Pattern 4: Test Helper Macros

Add macros to ResponseSequence for test setup:


Sources: src/ResponseSequence.php36-42 (push method)


Macro Binding Context

Macros are closures bound to the class instance, providing full access to protected and private members:


This allows macros to:

  • Access protected properties like $this->options in PendingRequest
  • Call protected methods for internal operations
  • Modify internal state while maintaining encapsulation

Sources: Macroable trait behavior (Hyperf framework)


Macro Lifecycle and Scope

Static Registration

Macros are registered statically per class and persist for the entire application lifecycle:


Instance Execution

While registration is static, execution occurs on instances:


Sources: src/Factory.php404-417 (Factory creating independent PendingRequest instances)


Class-Specific Macro Capabilities

Factory Macros

Factory macros can:

  • Return configured PendingRequest instances
  • Access the event dispatcher: $this->dispatcher
  • Manage global middleware: $this->globalMiddleware
  • Access test recording: $this->recorded
  • Create response sequences: $this->sequence()

Sources: src/Factory.php93-96 src/Factory.php175-178

PendingRequest Macros

PendingRequest macros can:

  • Chain with fluent configuration methods
  • Access and modify request options: $this->options
  • Register middleware: $this->middleware
  • Set before-sending callbacks: $this->beforeSendingCallbacks
  • Execute requests directly

Sources: src/PendingRequest.php92-210

Request Macros

Request macros can:

  • Access PSR-7 request: $this->request
  • Parse request data: $this->data()
  • Check headers and content types
  • Validate request structure

Sources: src/Request.php26-28 src/Request.php126-137

Response Macros

Response macros can:

  • Access PSR-7 response: $this->response
  • Utilize decoded JSON cache: $this->decoded
  • Access transfer stats: $this->transferStats
  • Check status codes
  • Transform response data

Sources: src/Response.php32-49

ResponseSequence Macros

ResponseSequence macros can:

  • Add responses to sequence: $this->responses
  • Configure empty behavior: $this->failWhenEmpty
  • Chain sequence builders
  • Create domain-specific test sequences

Sources: src/ResponseSequence.php19-31


Macro Registration Strategies

Application Bootstrap

Register global macros during application initialization:


Package-Provided Macros

Third-party packages can provide macros via service providers:


Test-Specific Macros

Register macros in test setup for test-specific functionality:


Sources: src/Factory.php310-317 (test assertion methods for reference)


Advanced: Conditional Macro Application

Macros can leverage the Conditionable trait used by PendingRequest:


Sources: src/PendingRequest.php40 (Conditionable trait)


Macro vs. Inheritance

AspectMacrosInheritance
Implementation TimeRuntimeCompile time
ScopeAll instancesSubclass instances only
ReusabilityAcross different contextsWithin class hierarchy
TestingCan be registered per testRequires class structure
PerformanceSlight overhead from closure executionNo overhead
FlexibilityCan be added/removed dynamicallyFixed at compile time

Recommendation: Use macros for:

  • Cross-cutting concerns applied to multiple classes
  • Domain-specific extensions without modifying core library
  • Test utilities and helpers
  • Dynamic behavior based on runtime configuration

Use inheritance for:

  • Performance-critical code paths
  • Core architectural patterns
  • Type-safe extensions
  • When you control the instantiation

Sources: src/PendingRequest.php40-41 src/Factory.php34-36

Refresh this wiki

On this page