Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
01508dd
Extract RootType::namespaces() and refactor FieldValue::parentNamespa…
spawnia Jul 10, 2026
3683814
Add RootResolverSignatureRector with type-fixing behavior
spawnia Jul 10, 2026
be9a69c
Add name normalization tests for RootResolverSignatureRector
spawnia Jul 10, 2026
e6f85c1
Document root resolvers and the RootResolverSignatureRector rule
spawnia Jul 10, 2026
89bcd0b
Require Larastan bootstrap for RootResolverSignatureRector
spawnia Jul 10, 2026
1110380
Use protected visibility in RootResolverSignatureRector
spawnia Jul 10, 2026
96d6bfb
Ignore docs/superpowers in .gitignore
spawnia Jul 10, 2026
9d88837
Fix isMissingRootParam producing duplicate param names
spawnia Jul 10, 2026
13435be
Validate paramNames element types in configure()
spawnia Jul 10, 2026
6d7dacd
Throw when resolver namespaces are empty (misconfigured bootstrap)
spawnia Jul 10, 2026
2ac1ac8
Refactor RootResolverSignatureRector for clarity
spawnia Jul 10, 2026
7acf822
Fix docs: sentence line break and missing $args insertion bullet
spawnia Jul 10, 2026
1840f90
Add missing test fixtures for fixObjectParam paths
spawnia Jul 10, 2026
03a4ef9
Add CHANGELOG entry for RootResolverSignatureRector
spawnia Jul 10, 2026
ebab0a4
Apply fixes from tooling (rector, php-cs-fixer, phpstan)
spawnia Jul 10, 2026
d9f02dd
Fix normalizeNames to rename variable usages in method body
spawnia Jul 10, 2026
4db7570
Use mixed $root in docs example for PHP 8.0/8.1 compat
spawnia Jul 10, 2026
5c95630
Replace assert with InvalidConfigurationException for paramNames
spawnia Jul 10, 2026
046cee7
Replace TODO placeholder with actual PR number in CHANGELOG
spawnia Jul 10, 2026
332fee5
Keep rector/rector installed in CI to validate Rector code
spawnia Jul 10, 2026
585638b
Keep larastan installed in PHPUnit CI job
spawnia Jul 10, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions .github/workflows/validate.yml
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ jobs:
key: php-${{ matrix.php-version }}-composer-${{ matrix.laravel-version }}-os-${{ matrix.os }}-composer-${{ matrix.composer.name }}

- name: "Remove conflicting dependencies that are not needed here"
run: composer remove --dev --no-update phpbench/phpbench rector/rector
run: composer remove --dev --no-update phpbench/phpbench

- name: "Remove Pennant for Laravel 9 because it is not compatible"
if: matrix.laravel-version == '^9'
Expand Down Expand Up @@ -168,7 +168,7 @@ jobs:
key: php-${{ matrix.php-version }}-composer-${{ matrix.laravel-version }}-os-${{ matrix.os }}-composer-${{ matrix.composer.name }}

- name: "Remove conflicting dependencies that are not needed here"
run: composer remove --dev --no-update larastan/larastan phpstan/phpstan-mockery phpbench/phpbench rector/rector
run: composer remove --dev --no-update phpstan/phpstan-mockery phpbench/phpbench

- name: "Remove Pennant for Laravel 9 because it is not compatible"
if: matrix.laravel-version == '^9'
Expand Down Expand Up @@ -224,7 +224,7 @@ jobs:
path: ~/.composer/cache
key: php-${{ matrix.php-version }}-composer-${{ matrix.laravel-version }}

- run: composer remove --dev phpbench/phpbench rector/rector --no-update
- run: composer remove --dev phpbench/phpbench --no-update

- run: composer require laravel/framework:${{ matrix.laravel-version }} --no-interaction --prefer-dist --no-progress

Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
.vscode
phpunit.xml
.gitpod.yml
docs/superpowers

# Generated files
.phpunit.result.cache
Expand Down
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@ You can find and compare releases at the [GitHub release page](https://github.co

## Unreleased

### Added

- Add `RootResolverSignatureRector` rule to auto-fix root resolver `__invoke` signatures https://github.com/nuwave/lighthouse/pull/2779

## v6.68.0

### Added
Expand Down
71 changes: 71 additions & 0 deletions docs/master/api-reference/resolvers.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,77 @@ function (mixed $root, array $args, GraphQLContext $context, ResolveInfo $resolv

The return value of this must fit the return type defined for the corresponding field from the schema.

## Root resolvers

Root resolvers are classes with an `__invoke` method that sit directly in the configured
`lighthouse.namespaces.queries` or `lighthouse.namespaces.mutations` namespaces.
Lighthouse calls them with positional arguments `($root, $args, $context, $resolveInfo)` where `$root` is always `null` for root types.

Omitting `$root` causes Lighthouse's positional `null` to bind to `$args`, producing TypeErrors at runtime.
The canonical signature for a root resolver is:

```php
use Nuwave\Lighthouse\Execution\ResolveInfo;
use Nuwave\Lighthouse\Support\Contracts\GraphQLContext;

class MyQuery
{
public function __invoke(mixed $root, array $args, GraphQLContext $context, ResolveInfo $resolveInfo)
{
// ...
}
}
```

On PHP 8.2+, you can use the more precise `null` type instead of `mixed`.
The Rector rule below automatically picks the correct type for your PHP version.

### Rector rule

Lighthouse ships a Rector rule that enforces correct `__invoke` signatures on root resolvers.
Enable it in your `rector.php`:

```php
use Nuwave\Lighthouse\Rector\RootResolverSignatureRector;
use Rector\Config\RectorConfig;

return static function (RectorConfig $rectorConfig): void {
$rectorConfig->rule(RootResolverSignatureRector::class);

// Required: Larastan bootstrap makes config() available
$rectorConfig->bootstrapFiles([
__DIR__ . '/vendor/larastan/larastan/bootstrap.php',
]);
};
```

The rule fixes:

- Missing `$root` parameter (detected when there is a single param typed `array` or untyped)
- Missing `$args` parameter when only `$root` is present
- Wrong type on the `$root` parameter (must be `null` on PHP 8.2+, `mixed` on earlier versions)
- Wrong type on `$args` (must be `array`)
- Wrong type on `$context` if present (must implement `GraphQLContext`)
- Wrong type on `$resolveInfo` if present (must be or extend `ResolveInfo`)

#### Name normalization

Optionally configure preferred parameter names:

```php
$rectorConfig->ruleWithConfiguration(RootResolverSignatureRector::class, [
'paramNames' => ['_', 'args', 'context', 'resolveInfo'],
]);
```

Use `null` at any position to skip renaming that parameter:

```php
$rectorConfig->ruleWithConfiguration(RootResolverSignatureRector::class, [
'paramNames' => [null, null, 'context', 'resolveInfo'],
]);
```

## Complexity function signature

The complexity function is used to calculate a query complexity score for a field.
Expand Down
Loading
Loading