A powerful and flexible parameter resolution library for PHP that automatically resolves function and method parameters from various sources including arrays, DI containers, and configuration.
- Multiple Resolution Strategies: Resolve parameters by name, position, type, or attributes
- DI Container Integration: Seamless integration with PSR-11 containers
- Attribute Support: Native PHP 8+ attributes (
#[Config]
,#[Inject]
) - Union Types: Full support for PHP 8 union types
- Extensible Architecture: Easy to add custom resolvers
- Zero Dependencies: Core functionality requires no external dependencies
- High Performance: Optimized resolver chain with early termination
composer require bermudaphp/di-resolver
use Bermuda\ParameterResolver\ParameterResolver;
use Bermuda\ParameterResolver\ArrayResolver;
use Bermuda\ParameterResolver\DefaultValueResolver;
// Create resolver with basic resolvers
$resolver = new ParameterResolver([
new ArrayResolver(), // Resolve from provided array
new DefaultValueResolver() // Use default values
]);
// Define a function
function greetUser(string $name, string $greeting = 'Hello', ?int $age = null) {
return "$greeting, $name" . ($age ? " (age: $age)" : "");
}
// Resolve parameters
$reflection = new ReflectionFunction('greetUser');
$parameters = $reflection->getParameters();
$resolvedParams = $resolver->resolve($parameters, [
'name' => 'John',
'age' => 25
]);
// Result: ['John', 'Hello', 25]
echo greetUser(...$resolvedParams); // "Hello, John (age: 25)"
Resolves parameters by name or position from provided array:
$resolver = new ArrayResolver();
// By name
$params = ['username' => 'john', 'email' => 'john@example.com'];
// By position
$params = [0 => 'john', 1 => 'john@example.com'];
Resolves parameters by object type scanning:
$resolver = new ArrayTypedResolver();
$params = [
'userService' => new UserService(),
'logger' => new Logger()
];
function processUser(UserService $service, Logger $logger) {
// Parameters resolved automatically by type
}
Resolves from PSR-11 DI containers with attribute support:
use Bermuda\DI\Attribute\Config;
use Bermuda\DI\Attribute\Inject;
$resolver = new ContainerResolver($container);
function createUser(
#[Config('database.host')] string $dbHost,
#[Inject('user.repository')] UserRepository $repo,
UserService $service // Resolved by type from container
) {
// All parameters resolved automatically
}
Uses parameter default values:
function processData(array $data, bool $validate = true, ?string $format = null) {
// $validate will be true, $format will be null if not provided
}
Resolves nullable parameters to null:
function optionalService(?LoggerInterface $logger = null) {
// $logger will be null if not resolvable
}
use Bermuda\ParameterResolver\ParameterResolver;
// Create resolver with all standard resolvers
$resolver = ParameterResolver::createDefaults($container);
class UserController
{
public function createUser(
#[Config('app.name')] string $appName,
#[Inject('user.validator')] UserValidator $validator,
UserRepository $repository, // From container by type
array $userData, // From provided parameters
bool $sendEmail = true, // Default value
?LoggerInterface $logger = null // Nullable fallback
) {
// All parameters resolved automatically
$user = new User($userData);
if ($validator->validate($user)) {
$repository->save($user);
if ($sendEmail && $logger) {
$logger->info("User created in $appName");
}
}
return $user;
}
}
// Usage
$method = new ReflectionMethod(UserController::class, 'createUser');
$resolvedParams = $resolver->resolve(
$method->getParameters(),
['userData' => $_POST, 'sendEmail' => false]
);
$controller = new UserController();
$user = $controller->createUser(...$resolvedParams);
The Config
attribute supports dot notation and various data sources:
use Bermuda\DI\Attribute\Config;
// Simple config access
function connectDatabase(#[Config('database.host')] string $host) {}
// With default values
function getApiKey(#[Config('api.key', 'default-key')] string $key) {}
// Disable dot notation
function getLiteralKey(#[Config('app.debug', explodeDots: false)] bool $debug) {}
// Deep nesting
function getNestedValue(
#[Config('services.external.api.endpoints.users')] string $endpoint
) {}
$config = new ArrayObject([
'database' => ['host' => 'localhost', 'port' => 3306]
]);
$container->set('config', $config);
function connect(#[Config('database.host')] string $host) {
// Works with ArrayAccess objects
}
class EnvironmentResolver implements ParameterResolverInterface
{
public function resolve(
ReflectionParameter $parameter,
array $providedParameters = [],
array $resolvedParameters = []
): ?array {
$envVar = 'APP_' . strtoupper($parameter->getName());
$value = $_ENV[$envVar] ?? null;
return $value !== null ? [$parameter->getPosition(), $value] : null;
}
}
// Add to resolver chain
$resolver = new ParameterResolver([
new EnvironmentResolver(),
new ArrayResolver(),
new DefaultValueResolver()
]);
function flexibleHandler(string|UserService $handler, int|float $value) {
// Resolves first matching type from union
}
$params = [
'UserService' => new UserService(), // Matches UserService from union
'value' => 42 // Matches int from union
];
$resolver = new ParameterResolver([
new ArrayResolver(), // Priority 1: Explicit parameters
new ArrayTypedResolver(), // Priority 2: Type matching
new ContainerResolver($container), // Priority 3: DI container
new DefaultValueResolver(), // Priority 4: Default values
new NullableResolver() // Priority 5: Nullable fallback
]);
use Bermuda\ParameterResolver\ParameterResolutionException;
try {
$resolvedParams = $resolver->resolve($parameters, $providedParams);
} catch (ParameterResolutionException $e) {
echo "Failed to resolve parameter: " . $e->parameter->getName();
echo "Provided parameters: " . print_r($e->providedParameters, true);
echo "Already resolved: " . print_r($e->resolvedParameters, true);
}
- Order resolvers by frequency - put most commonly used resolvers first
- Use typed parameters when possible for faster ArrayTypedResolver matching
- Avoid deep nesting in Config paths for better performance
- Cache reflection objects when resolving the same signatures repeatedly
- PHP 8.4 or higher
MIT License. See LICENSE for details.