Skip to content

Pass scalar overrides explicitly to keep lazy type loading lazy on graphql-php >= 15.31#2772

Merged
spawnia merged 5 commits into
nuwave:masterfrom
deskpro:explicit-scalar-overrides
Jul 23, 2026
Merged

Pass scalar overrides explicitly to keep lazy type loading lazy on graphql-php >= 15.31#2772
spawnia merged 5 commits into
nuwave:masterfrom
deskpro:explicit-scalar-overrides

Conversation

@tmoitie

@tmoitie tmoitie commented Jun 11, 2026

Copy link
Copy Markdown
Contributor

Resolves #2771

  • Added or updated tests
  • Documented user facing changes
  • Updated CHANGELOG.md (skip for docs-only changes)

Changes

On webonyx/graphql-php >= 15.31.0, the executor's first built-in scalar lookup triggers scalar-override discovery, which resolves the lazy types callable (TypeRegistry::possibleTypes()) and eagerly builds every type in the schema from the AST — on every request under PHP-FPM. Details and measurements in #2771.

webonyx/graphql-php#1927 adds SchemaConfig::setScalarOverrides(?array): when overrides are passed explicitly (including an empty array), the scan of types is skipped entirely and lazy loading stays lazy.

This PR makes SchemaBuilder::build() determine the overrides cheaply from the document AST — a scalar override is a user-defined type named after a built-in scalar, and $documentAST->types is keyed by name — and pass them explicitly. For the common case (no built-in scalar names redefined in the SDL) this is five isset() checks and an explicit empty array.

The call is guarded with method_exists($config, 'setScalarOverrides'), following the pattern of the query complexity guard from #2637, so the webonyx/graphql-php: ^15 constraint is unchanged. The guard (and the corresponding test skips) can be removed once the minimum graphql-php version includes the method.

Tests added:

  • explicit empty overrides are set for a plain schema
  • a redefined built-in scalar (scalar String @scalar(class: "Email")) is passed as an override
  • regression: looking up a built-in scalar on the schema does not resolve unrelated types (this test fails without the SchemaBuilder change when running against graphql-php with Fix phpbench #1927 applied)

All three tests are skipped on graphql-php versions without setScalarOverrides; I verified them locally against the #1927 branch (15 tests, 41 assertions, 0 skipped) and confirmed the regression test fails without the fix.

Draft status: marked draft until webonyx/graphql-php#1927 is merged and released.

Breaking changes

None. Behavior is unchanged on graphql-php versions without setScalarOverrides; on versions with it, schemas behave identically but built-in scalar lookups no longer force full type resolution.

🤖 Generated with Claude Code

tmoitie and others added 3 commits June 11, 2026 12:54
On webonyx/graphql-php >= 15.31.0, the first lookup of a built-in scalar
triggers scalar-override discovery, which resolves the lazy types callable
and eagerly builds every type in the schema from the AST on every request.

When SchemaConfig::setScalarOverrides is available, determine the overrides
cheaply from the document AST and pass them explicitly so the scan is
skipped and the types callable stays unresolved.

Fixes nuwave#2771.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@tmoitie
tmoitie marked this pull request as ready for review July 20, 2026 10:18
Comment thread src/Schema/SchemaBuilder.php Outdated
Comment thread tests/Unit/Schema/SchemaBuilderTest.php Outdated
tmoitie and others added 2 commits July 22, 2026 15:42
Move override detection into TypeRegistry::scalarOverrides() so it also
covers types registered programmatically via overwrite()/overwriteLazy(),
not only SDL definitions - the types scan on graphql-php >= 15.31 finds
those too, so explicit overrides must match.

Fix the laziness test guard referencing SchemaConfig without an import,
which made PHPStan fail on CI and silently skipped the test at runtime.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Updates Lighthouse’s schema construction to keep lazy type loading truly lazy on webonyx/graphql-php >= 15.31 by explicitly passing scalar overrides to SchemaConfig when the new API is available, avoiding an eager types scan triggered by built-in scalar lookup.

Changes:

  • Add a guarded call in SchemaBuilder::build() to pass scalar overrides explicitly when SchemaConfig::setScalarOverrides() exists.
  • Add TypeRegistry::scalarOverrides() to compute overridden built-in scalars without forcing full type resolution.
  • Add unit tests covering explicit empty overrides, overridden built-in scalars (SDL + programmatic), and a regression test for avoiding eager resolution; update CHANGELOG.md.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 1 comment.

File Description
tests/Unit/Schema/SchemaBuilderTest.php Adds tests validating scalar override registration and lazy-resolution regression.
src/Schema/TypeRegistry.php Introduces scalar override discovery helper used by schema building.
src/Schema/SchemaBuilder.php Passes scalar overrides to graphql-php conditionally to preserve laziness.
CHANGELOG.md Documents the fix for lazy schema loading on graphql-php >= 15.31.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +242 to +266
/**
* Built-in scalar types that are overridden in this schema.
*
* A scalar override is a type named after a built-in scalar such as `String`,
* defined in the schema or registered programmatically.
*
* @return array<int, \GraphQL\Type\Definition\ScalarType>
*/
public function scalarOverrides(): array
{
$overrides = [];
foreach (Type::BUILT_IN_SCALAR_NAMES as $name) {
if (
isset($this->types[$name])
|| isset($this->documentAST->types[$name])
|| isset($this->lazyTypes[$name])
) {
$override = $this->get($name);
assert($override instanceof ScalarType);
$overrides[] = $override;
}
}

return $overrides;
}
@spawnia
spawnia merged commit 5cd63bf into nuwave:master Jul 23, 2026
90 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.

Lazy schema becomes eager on every request with graphql-php >= 15.31: built-in scalar lookup resolves possibleTypes()

3 participants