VOOZH about

URL: https://deepwiki.com/hypervel/auth/2.2-user-resolver

⇱ User Resolver | hypervel/auth | DeepWiki


Loading...
Menu

User Resolver

Purpose and Scope

The User Resolver is a lightweight invokable class that provides dependency injection support for retrieving the currently authenticated user. It serves as the container binding target for the Authenticatable contract, allowing any service to type-hint Authenticatable and automatically receive the authenticated user from the active guard.

The resolver operates through a closure-based system managed by AuthManager, enabling request-scoped customization and lazy evaluation of authentication state. The actual user retrieval is delegated to guards, maintaining separation between the DI resolution mechanism and authentication logic.

This document covers the UserResolver class at src/UserResolver.php1-18 its integration with AuthManager's user resolver closure system, and how guards use this mechanism for user retrieval. For guard implementation details, see page 2.3. For the AuthManager factory pattern, see page 2.1.

Architecture Overview

The User Resolver implements a three-tier architecture: the UserResolver class binds to the DI container, the AuthManager manages the resolution closure, and guards perform the actual user retrieval.

Resolution Flow Diagram


Sources: src/UserResolver.php12-16 src/AuthManager.php198-205 src/AuthManager.php52-54 src/AuthManager.php60-65

Integration with Guards

Guards use the user resolver indirectly through the AuthManager. When a guard needs to be set as the default, the shouldUse() method updates the user resolver to ensure subsequent resolutions use that guard.


Sources: src/UserResolver.php1-18 src/AuthManager.php22-55 src/AuthManager.php166-175 src/AuthManager.php198-217

Component Structure

UserResolver Class

The UserResolver class at src/UserResolver.php1-18 is a minimal invokable that serves as the DI container binding for the Authenticatable contract. Its sole responsibility is to retrieve the user resolver closure from AuthManager.

Class Definition

ElementTypeDescription
__invoke(ContainerInterface $container)arrayRetrieves AuthFactoryContract from container and returns its userResolver() result

The implementation is straightforward:


The method returns an array containing the closure, which the container framework then executes to obtain the actual user.

Sources: src/UserResolver.php10-17

Class Relationships


Sources: src/UserResolver.php1-18 src/AuthManager.php22-255 src/Contracts/Factory.php

AuthManager Integration

The AuthManager at src/AuthManager.php22-255 manages the user resolver closure through a protected property and three primary methods. The closure is initialized during construction and can be overridden on a per-request basis through Hyperf's Context system.

User Resolver Property

The $userResolver property at src/AuthManager.php41 stores the default closure for user resolution:


This property is initialized in the constructor at src/AuthManager.php48-55:


The default closure accepts an optional guard name and delegates to that guard's user() method. If no guard is specified, the default guard is used via src/AuthManager.php60-65

Sources: src/AuthManager.php41 src/AuthManager.php48-55

User Resolver Methods

The AuthManager provides three methods for interacting with the user resolver system:

MethodSignaturePurpose
userResolver()ClosureReturns the active resolver closure (Context override or default property)
resolveUsersUsing(Closure)staticStores a custom resolver in Context for request-scoped override
shouldUse(?string)voidSets the default guard and updates resolver to use that guard
userResolver() Method

Located at src/AuthManager.php198-205 this method implements a two-tier lookup:


The Context key __auth.resolver takes precedence, allowing request-scoped customization without modifying the base property.

resolveUsersUsing() Method

Located at src/AuthManager.php212-217 this method sets a custom resolver in Context:


This enables runtime override of user resolution logic, primarily used by shouldUse() when switching default guards.

shouldUse() Method

Located at src/AuthManager.php166-175 this method coordinates guard switching with user resolver updates:


This ensures the user resolver always uses the currently active default guard.

Sources: src/AuthManager.php198-205 src/AuthManager.php212-217 src/AuthManager.php166-175

User Resolver Lifecycle

Initialization Phase

The user resolver is initialized during application bootstrap when ConfigProvider registers the authentication bindings:

Bootstrap Sequence


Sources: composer.json47-49 src/AuthManager.php48-55

Default Resolver Initialization

The default closure at src/AuthManager.php52-54 creates a guard-delegating resolver:


This closure captures $this (the AuthManager instance) and will call guard($guard)->user() when executed. The $guard parameter is optional, defaulting to the configured default guard.

Sources: src/AuthManager.php52-54

Resolution Process

When a service declares a dependency on Authenticatable, the container executes a multi-step resolution process:

Resolution Flow


Sources: src/UserResolver.php12-16 src/AuthManager.php198-205 src/AuthManager.php60-65 src/AuthManager.php52-54

Step-by-Step Breakdown

StepComponentFile LocationAction
1Container-Receives type-hint for Authenticatable
2Containercomposer.json47-49Looks up binding to UserResolver
3UserResolversrc/UserResolver.php12-16Invokes __invoke($container)
4UserResolversrc/UserResolver.php14-15Retrieves AuthFactoryContract from container
5AuthManagersrc/AuthManager.php198-205Calls userResolver() method
6AuthManagersrc/AuthManager.php200-201Checks Context::get('__auth.resolver')
7aAuthManagersrc/AuthManager.php201Returns Context resolver if exists
7bAuthManagersrc/AuthManager.php204Returns $userResolver property if no Context
8Container-Executes returned closure
9Closuresrc/AuthManager.php52-54Calls $this->guard($guard)
10AuthManagersrc/AuthManager.php60-65Resolves guard instance
11GuardVariousCalls user() method on guard
12GuardVariousReturns Authenticatable or null
13Container-Injects result into service

Sources: src/UserResolver.php12-16 src/AuthManager.php198-205 src/AuthManager.php52-54 src/AuthManager.php60-65

Context-Scoped Resolution

The user resolver implements request-scoped customization through Hyperf's Context system at src/AuthManager.php198-205 This enables per-request override of user resolution logic without affecting other concurrent requests.

Context Key Architecture

The resolver uses a dedicated Context key for storing request-specific overrides:

Context KeyTypePurpose
__auth.resolverClosure|nullRequest-scoped user resolver override
__auth.defaults.guardstring|nullRequest-scoped default guard name

Context Precedence Flow


Sources: src/AuthManager.php198-205 src/AuthManager.php156-161

Context Storage Mechanism

The AuthManager::userResolver() method at src/AuthManager.php198-205 implements a two-tier lookup:


The method first checks Context::get('__auth.resolver'). If a resolver exists in Context, it is returned. Otherwise, the default $userResolver property is used. This enables request-scoped customization without modifying shared state.

Sources: src/AuthManager.php198-205

Setting Custom Resolvers

The resolveUsersUsing() method at src/AuthManager.php212-217 provides the interface for setting request-scoped resolvers:


This stores the custom resolver in Context using the key __auth.resolver, affecting only the current request scope.

Sources: src/AuthManager.php212-217

Guard Switching Integration

The shouldUse() method at src/AuthManager.php166-175 demonstrates the primary use case for context-scoped resolvers:


When the default guard changes, shouldUse() updates both the default guard name (via setDefaultDriver() at src/AuthManager.php180-183) and the user resolver. This ensures subsequent user resolutions use the new default guard.

Guard Switching Flow


Sources: src/AuthManager.php166-175 src/AuthManager.php180-183 src/AuthManager.php212-217

Usage Patterns

Dependency Injection Pattern

The primary usage pattern is dependency injection of the Authenticatable contract in service constructors:


Sources: src/UserResolver.php12-16 src/AuthManager.php198-205 src/AuthManager.php52-54

Explicit Guard Resolution

The default user resolver closure at src/AuthManager.php52-54 accepts an optional guard parameter:


This allows resolution with a specific guard:


However, this pattern is rarely used directly, as guards are typically accessed via AuthManager::guard($name)->user().

Sources: src/AuthManager.php52-54

Middleware Guard Switching

The Authenticate middleware uses shouldUse() at src/AuthManager.php166-175 to set the active guard:


This pattern ensures:

  1. The default guard is updated in Context via setDefaultDriver() at src/AuthManager.php180-183
  2. The user resolver is updated to use the new default
  3. Subsequent DI resolutions of Authenticatable use the new guard

Middleware Integration Example


Sources: src/AuthManager.php166-175 src/AuthManager.php180-183 src/AuthManager.php212-217

Integration with Guards

The user resolver integrates with guards through the AuthManager, which acts as a factory for guard instances. The resolver closure delegates to guards for actual user retrieval.

Guard Delegation Model


Sources: src/AuthManager.php52-54 src/AuthManager.php60-65 src/AuthManager.php72-91 src/AuthManager.php104-125

Guard Resolution Process

When the resolver closure executes $this->guard($guard)->user(), the following occurs:

StepMethodFile LocationAction
1Closure executionsrc/AuthManager.php52-54Calls $this->guard($guard)
2AuthManager::guard()src/AuthManager.php60-65Determines guard name (default or specified)
3Guard cache checksrc/AuthManager.php64Checks $guards[$name] cache
4aCache hitsrc/AuthManager.php64Returns cached guard instance
4bCache misssrc/AuthManager.php64Calls resolve($name)
5AuthManager::resolve()src/AuthManager.php72-91Resolves guard configuration
6Driver methodsrc/AuthManager.php82-86Calls create{Driver}Driver()
7Guard instantiationsrc/AuthManager.php104-125Creates guard with user provider
8Guard::user()VariousGuard retrieves user

Sources: src/AuthManager.php52-54 src/AuthManager.php60-65 src/AuthManager.php72-91 src/AuthManager.php104-125

User Provider Integration

Guards use user providers (see page 2.4) to retrieve user data. The user resolver is agnostic to the provider implementation:


Sources: src/AuthManager.php52-54 src/AuthManager.php104-125

Key Implementation Details

Request-Scoped Behavior

Both the default guard setting and custom user resolvers are stored in Hyperf Context, making them request-scoped. This ensures:

  • Each request has isolated authentication state
  • No state leakage between concurrent requests
  • Guards and resolvers can be customized per-request without affecting other requests

The Context keys used are:

Sources: src/AuthManager.php156-161 src/AuthManager.php200-201 src/AuthManager.php214

Closure-Based Design

The user resolver uses a closure-based design rather than direct method calls. This provides:

  • Lazy evaluation: User is only retrieved when actually needed
  • Flexibility: The resolver can be swapped at runtime
  • Testability: Easy to mock for testing
  • Decoupling: Services don't need direct references to AuthManager

The closure signature is function ($guard = null), allowing optional guard specification.

Sources: src/AuthManager.php41 src/AuthManager.php52-54

Guard Delegation Pattern

The user resolver doesn't retrieve users directly; it delegates to guards. This maintains separation of concerns:

  • UserResolver: Provides the mechanism to resolve users
  • AuthManager: Manages which guard to use
  • Guards: Handle actual authentication and user retrieval

This layered approach allows the authentication strategy (guard) to be changed without affecting the user resolver contract.

Sources: src/AuthManager.php52-54 src/AuthManager.php60-65

Refresh this wiki

On this page