Skip to content

resettable schemas, getCurrentSchemaName for TypeResolver, and IsPublic support for InputObject fields#1241

Open
vlydev wants to merge 6 commits intooverblog:masterfrom
vlydev:master
Open

resettable schemas, getCurrentSchemaName for TypeResolver, and IsPublic support for InputObject fields#1241
vlydev wants to merge 6 commits intooverblog:masterfrom
vlydev:master

Conversation

@vlydev
Copy link

@vlydev vlydev commented Mar 17, 2026

Q A
Bug fix? no
New feature? yes
BC breaks? no
Deprecations? no
Tests pass? yes
Documented? yes
License MIT

Summary

This PR adds three independent improvements to the bundle, primarily motivated by long-running process compatibility (e.g. RoadRunner, Swoole, FrankenPHP) and better ACL
control over input types.


  1. Resettable schemas (SchemaBuilder, Executor, AbstractResolver)

What changed:

  • SchemaBuilder and Executor now implement ResetInterface
  • A new resettable: true option can be set per schema in config
  • ExtensibleSchema gained isResettable()/setIsResettable() methods
  • AbstractResolver now properly separates factories ($solutionsFactory) from built instances ($solutions) and implements reset() — clearing only the built instances, not the
    factories

In long-running process environments (RoadRunner, Swoole, ReactPHP), the Symfony kernel's reset() cycle is called between requests. Previously, built schemas were cached via a
static variable inside the getBuilder() closure, which meant they survived resets entirely — causing stale type registries and memory growth over time.

This change moves schema caching into SchemaBuilder::$builders (an instance property), so reset() can selectively evict schemas marked as resettable: true. Non-resettable
schemas (the default) are kept across resets for performance. The same principle applies to AbstractResolver: factories are registered once at boot and survive resets, while
resolved instances are cleared so they can be rebuilt fresh on the next request.

  # config/packages/graphql.yaml
  overblog_graphql:                                                                                                                                                               
      definitions:                                                                                                                                                                
          schema:                                                                                                                                                                 
              default:                                                                                                                                                            
                  query: RootQuery                                                                                                                                                
                  resettable: true   # rebuilt on kernel reset         

  1. TypeResolver::getCurrentSchemaName()

What changed:

  • Added a public getter getCurrentSchemaName(): ?string alongside the existing setCurrentSchemaName()

The current schema name is set internally during schema build but was previously inaccessible from outside the resolver. Services and extensions that need to apply
schema-specific logic (e.g. different ACL rules per schema, custom type loaders, multi-schema middleware) had no way to read which schema is currently being resolved without
injecting additional state. This getter exposes what was already tracked internally, with zero behavioral change.


  1. #[IsPublic] support on InputObject fields

What changed:

  • InputObjectTypeDefinition now accepts a public key on field-level config
  • MetadataParser reads #[IsPublic] attributes (and @ispublic annotations) on InputObject class properties and maps them to public in the field configuration
  • Using #[IsPublic] on a property without #[Field] throws InvalidArgumentException (consistent with the existing behavior for #[Access] on object types)

#[IsPublic] was already supported on ObjectType fields and at the provider level, but InputObject fields had no equivalent. This gap meant that input fields carrying sensitive
data (e.g. an adminNotes field on a search input) could not be conditionally hidden via expression language — the only option was to create separate input types. This change
brings InputObject field visibility in line with ObjectType field visibility, using the same expression-language mechanism already present in the bundle.

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.

1 participant