Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Arguments Resolver Laravel Package

rybakit/arguments-resolver

Lightweight PHP library that resolves callable arguments via reflection, matching values from arrays or containers to parameter types, names, and defaults. Automatically fills optional parameters and helps build invokers or small DI containers. Works with closures, functions, methods, and invokable...

View on GitHub
Deep Wiki
Context7

Getting Started

Install with Composer:

composer require rybakit/arguments-resolver

The public surface is tiny — start with Rybakit\ArgumentsResolver\ArgumentsResolver and its resolve() method. You give it a callable and an associative array of candidate arguments (keyed by parameter name), and it hands back the ordered positional array you should actually pass to the callable:

use Rybakit\ArgumentsResolver\ArgumentsResolver;

$resolver = new ArgumentsResolver();

$callable = function (string $name, int $age = 30, ...$meta) { /* ... */ };

$args = $resolver->resolve($callable, [
    'name' => 'Alice',
    'meta' => ['role' => 'admin'], // unknown to the signature
    'age'  => 41,
]);

$callable(...$args); // ['Alice', 41]

The first real use case is any place you have a "bag of context" (a PSR-7 request, a container, an event payload) but a callable that expects a specific, typed subset. That's the sweet spot: controllers, listeners, middleware, and command handlers.

Look first at ArgumentsResolverInterface (for testing/mocking) and the resolve() method — that's 90% of the library. Read the README's examples for variadics and defaults; there's not much else to learn.

Implementation Patterns

Service-layer wrapper. Don't sprinkle new ArgumentsResolver() across the codebase. Bind it in your container as a singleton (it's stateless) and inject ArgumentsResolverInterface:

$this->app->singleton(ArgumentsResolverInterface::class, ArgumentsResolver::class);

This makes it swappable in unit tests and gives you one place to decorate or cache later.

Controller/action invocation. Given a route target [$controller, $method] and a request-derived array of ['id' => 42, 'request' => $request], resolve and invoke. The resolver's job is to strip id/request down to only what the method declares and apply defaults — your router stays dumb.

$args = $resolver->resolve([$controller, $method], $context);
$response = ($controller)->{$method}(...$args);

Event listeners with DI. Same pattern: each listener declares the event it cares about plus any services it wants, and the dispatcher passes the union of ['event' => $event] + $container->resolvedServices() through the resolver. Listeners only pull what they use.

Middleware / pipeline. For a middleware signature like handle(Request $request, callable $next, Logger $logger = null), resolve the middleware plus a fixed $next closure from the shared context. This lets you drop the middleware into any pipeline regardless of extra dependencies.

Handler sets in a command bus. Build a ['command' => $command, 'repo' => $repo, ...] bag once and hand it to every handler — each one extracts what it needs. This is much cleaner than passing a giant DTO around.

Partial application. A neat side use: call resolve() on a closure, store the resulting args, and later $closure(...$args) after merging — useful for deferred invocation and testing callables in isolation.

Wrap for caching. Since the resolver reflects on every call, wrap it in a small decorator that caches by spl_object_hash (objects), Class::method strings, or Closure identity. See gotchas below.

Gotchas and Tips

Reflection on every call. resolve() uses ReflectionFunction/ReflectionMethod each invocation. On hot paths (per-request routing is fine; per-item loops are not), memoize results keyed by the callable and the set of parameter names requested. Build the wrapper yourself — the library doesn't cache.

By-reference parameters silently break. If a callable declares &$value, the resolver returns a value, not a reference, so assignments inside the callable won't propagate back. Avoid by-ref params in code you route through the resolver, or handle those callables manually.

Nullable/default semantics. A missing key uses the declared default; a key present with null uses null. If the parameter is non-nullable and you pass null, you'll get a TypeError at call time, not resolve time — the resolver doesn't validate types. Treat the type system as the guard rail, not this library.

No type coercion. The resolver doesn't cast. If a container returns an int where the callable wants a string, PHP's coercion rules (or a TypeError under strict types) apply at the call site. Validate in your context-builder if this matters.

Extra keys are ignored. The bag can contain anything — only keys matching parameter names are used. That's the feature, but it also means a typo ('userId' vs 'user') silently falls back to the default. Log or lint your context keys if you have a lot of them.

Variadics. Variadic parameters absorb whatever lands in their named key as a spread — pass an array, not a single item. Don't assume a variadic will be populated just because it's declared.

Magic methods. __call/__callStatic route through a string like 'Class::method' that reflection can't see; the resolver will resolve against the magic-method signature (usually none) and misbehave. Normalize magic callables to real Closures first if you support them.

Internal functions. Reflection on some internal PHP functions has incomplete default-value info. Test any built-in you pass through; prefer wrapping them in a userland closure to get reliable defaults.

Closures are fine, first-class callables are fine. $obj->method(...) (PHP 8.1) and Closure::fromCallable([$obj, 'method']) both reflect correctly. Use these in tests where you want an exact callable identity for caching.

Extend by composition, not inheritance. The resolver is small and stateless; decorate it (cache, logging, metrics) rather than subclassing. Keep the interface type in signatures so decorators drop in cleanly.

Debugging tip. When a callable receives the wrong value, dump $resolver->resolve($callable, $context) before the call — that's the exact argument list, ordered by the signature, which is often easier to reason about than the call stack.

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
tequilarapido/trackit
gregsphotography/site-builder-filament
cabaoctavio/laravel-query-log
gregsphotography/site-builder-components
io-digital/clickatell
snowsoft/laravel-admin
oxygen/auth
relicsoftware/barakah-payment-gateway
tobya/work-with-composer
equipc/laravel-email-validator
equipc/laravel-email-database-log
adedsec/nova-translated-labels
wazza/laravel-db-encryption
hokny/laravel-generator
vonsogt/backup
jengo/queues
jeremykenedy/laravel-observability
coleus/frame
thtg88/journalism
filagora/filagora-ai-forums