VOOZH about

URL: https://deepwiki.com/hypervel/config/9.3-priority-definitions-and-dependencies

⇱ Priority Definitions and Dependencies | hypervel/config | DeepWiki


Loading...
Menu

Priority Definitions and Dependencies

Purpose and Scope

This document explains the special handling of PriorityDefinition objects within dependency injection configurations during the provider configuration merging process. The ProviderConfig system applies custom merge logic specifically to the dependencies configuration key when it contains PriorityDefinition instances from Hyperf's dependency injection container.

For general configuration merging strategies, see Configuration Merging Strategies. For an overview of the provider configuration system, see Provider Config Discovery and Merging.

Priority Definitions Overview

Priority definitions are instances of Hyperf\Di\Definition\PriorityDefinition used by Hyperf's dependency injection container to manage multiple implementations of the same interface with priority-based resolution. These objects contain an ordered list of implementations where higher priority values take precedence.

In the context of configuration merging, PriorityDefinition objects require special handling because they are not simple scalar values or arrays—they are objects with internal state that must be merged programmatically using their own merge() method rather than being overwritten.

Sources: src/ProviderConfig.php9

Configuration Context

Where Priority Definitions Appear

Priority definitions appear exclusively within the dependencies configuration key. This key maps interface names to their implementations:


The dependencies key is processed by Hyperf's DI container to register service bindings. When multiple packages contribute implementations for the same interface with different priorities, the system must merge these PriorityDefinition objects rather than replacing them.

Sources: src/ProviderConfig.php113-128

Special Merge Logic

Standard vs. Priority Definition Handling

The merge() method in ProviderConfig applies two different merge strategies:

Configuration TypeMerge Strategy
Regular keys (arrays, scalars)Recursive merge using mergeTwo()
dependencies with PriorityDefinitionSpecial accumulation with PriorityDefinition::merge()

The distinction exists because PriorityDefinition objects are stateful containers that maintain internal priority ordering. Simply applying recursive array merge logic would treat them as opaque values and overwrite earlier definitions instead of combining their priority lists.

Sources: src/ProviderConfig.php100-131

The Priority Definition Merge Algorithm


Algorithm for Merging Priority Definitions

Sources: src/ProviderConfig.php112-128

Implementation Details

Phase 1: Standard Merge

The merge process begins by applying the standard recursive merge algorithm to all configuration arrays:


This phase uses mergeTwo() to merge all top-level keys including dependencies. However, for dependencies containing PriorityDefinition objects, this standard merge is insufficient because PriorityDefinition instances are objects that cannot be meaningfully merged using array semantics.

Sources: src/ProviderConfig.php106-110

Phase 2: Priority Definition Re-merge

After the standard merge, a special post-processing phase handles the dependencies key:


This phase:

  1. Resets $result['dependencies'] to an empty array
  2. Iterates through all input arrays in order
  3. Processes each dependency binding individually
  4. Accumulates PriorityDefinition objects using their merge() method
  5. Overwrites non-PriorityDefinition bindings (standard behavior)

Sources: src/ProviderConfig.php113-128

Merge Behavior Matrix

Existing BindingNew BindingResult
Not existsAny valueSet new value
Scalar/ArrayAny valueOverwrite with new value
PriorityDefinitionPriorityDefinitionCall depend->merge($value)
PriorityDefinitionScalar/ArraySkip (no action)

The key insight is that when a PriorityDefinition already exists for a binding, only another PriorityDefinition can contribute to it. Scalar or array bindings from later providers are ignored to preserve the priority-based resolution semantics.

Sources: src/ProviderConfig.php117-126

Code Entity Mapping


Relationship Between ProviderConfig Merge Logic and PriorityDefinition Objects

Sources: src/ProviderConfig.php26-131

Usage Example

Multiple Providers Contributing Priorities

Consider three packages contributing dependency bindings for the same interface:

Package A configuration:


Package B configuration:


Package C configuration:


After merging through ProviderConfig::merge(), the resulting dependencies array contains a single PriorityDefinition for LoggerInterface::class with all three implementations ordered by priority:

  • DatabaseLogger::class (priority 20)
  • CloudLogger::class (priority 15)
  • FileLogger::class (priority 10)

Sources: src/ProviderConfig.php112-128

Integration Points

Entry Point: Provider Loading

The priority definition merge logic is invoked during the provider loading process:

ProviderConfig::load()
 └─> loadProviders($providers)
 └─> merge(...$providerConfigs)
 └─> Special dependencies handling

This occurs during application bootstrap when ConfigFactory calls ProviderConfig::load() to aggregate all provider configurations before merging with file-based configurations.

Sources: src/ProviderConfig.php26-54 src/ProviderConfig.php56-75

Dependency Injection Container

The merged dependencies configuration is ultimately consumed by Hyperf's DI container. The container reads PriorityDefinition objects and uses their internal priority ordering to resolve which implementation to inject when multiple candidates exist for an interface.

The special merge handling ensures that all provider contributions are accumulated into coherent PriorityDefinition objects rather than later providers overwriting earlier ones.

Sources: src/ProviderConfig.php9

Technical Constraints

Instance Check Requirement

The merge algorithm relies on instanceof checks to identify PriorityDefinition objects:


This means that custom priority definition implementations that do not extend Hyperf\Di\Definition\PriorityDefinition will not receive special merge handling and will be treated as regular values (overwritten by later providers).

Sources: src/ProviderConfig.php118-121

One-Way Merge

When an existing binding is a PriorityDefinition but a later provider contributes a non-PriorityDefinition value, the algorithm skips the new value:


This design choice prioritizes maintaining priority-based resolution semantics once they are established. A provider cannot "downgrade" a priority-based binding to a simple binding.

Sources: src/ProviderConfig.php123-125

Summary Table

AspectDetails
PurposeEnable multiple providers to contribute dependency bindings with priorities
Trigger Conditiondependencies key exists in merged configuration
Key ClassHyperf\Di\Definition\PriorityDefinition
Merge MethodPriorityDefinition::merge() called on existing instances
Implementation Locationsrc/ProviderConfig.php112-128
PhasePost-processing after standard recursive merge
Override BehaviorPriorityDefinition accumulates; scalars overwrite; mixed preserves priority

Sources: src/ProviderConfig.php112-128