Skip to content

[13.x] Fix nullable return types on the route binding registrar - #61124

Merged
taylorotwell merged 1 commit into
laravel:13.xfrom
dfinchenko:fix-binding-registrar-nullable-types
Aug 10, 2026
Merged

[13.x] Fix nullable return types on the route binding registrar#61124
taylorotwell merged 1 commit into
laravel:13.xfrom
dfinchenko:fix-binding-registrar-nullable-types

Conversation

@dfinchenko

Copy link
Copy Markdown
Contributor

Illuminate\Contracts\Routing\BindingRegistrar::getBindingCallback() documents @return \Closure, but its only implementation returns null whenever the given key has no registered binder:

public function getBindingCallback($key)
{
    if (isset($this->binders[$key = str_replace('-', '_', $key)])) {
        return $this->binders[$key];
    }
}

Broadcaster::binder() has the same gap. It documents @return \Illuminate\Contracts\Routing\BindingRegistrar, but assigns null when no registrar is bound in the container:

$this->bindingRegistrar = Container::getInstance()->bound(BindingRegistrar::class)
    ? Container::getInstance()->make(BindingRegistrar::class)
    : null;

Because both docblocks claim non-null, static analysis reports the framework's own null handling as dead code. Running PHPStan over the contract, the router and the broadcaster (level 6, checkPhpDocMethodSignatures: true):

Broadcaster.php:231: Left side of && is always true.
Broadcaster.php:231: Right side of && is always true.
Broadcaster.php:235: Unreachable statement - code above always terminates.
Broadcaster.php:300: Negated boolean expression is always false.

Those are the if ($binder && $binder->getBindingCallback($key)) guard and the return $value; fallback in resolveExplicitBindingIfPossible(), plus the lazy initialization in binder(). Adding |null to the three docblocks clears all four.

The Route facade already documents the real type: @method static \Closure|null getBindingCallback(string $key).

Docblocks only, no behavior change.

@taylorotwell
taylorotwell merged commit 6a917a7 into laravel:13.x Aug 10, 2026
54 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants