VOOZH about

URL: https://deepwiki.com/mathsgod/light/4.1-schema-generation-and-type-system

⇱ Schema Generation and Type System | mathsgod/light | DeepWiki


Loading...
Last indexed: 31 January 2026 (cf9511)
Menu

Schema Generation and Type System

This document explains how the Light framework automatically generates its GraphQL schema from PHP code using GraphQLite, including the type mapping system, attribute-based type declarations, and custom type mappers for database integration.

For information about specific GraphQL types and resolvers, see Root Query Type (Light\Type\App) and Controllers. For authentication/authorization annotations that work with the type system, see Permission Checking.


Overview

The Light framework uses GraphQLite to automatically generate a complete GraphQL schema from annotated PHP classes. The system introspects classes in configured namespaces, discovers types and fields through PHP attributes, and creates a fully functional GraphQL API without manual schema definition files.

The schema generation process happens during application initialization and is cached for performance. Type mapping handles conversion between PHP's type system and GraphQL's type system, with custom mappers extending support for framework-specific types like database queries.

Sources: src/App.php121-126


Schema Generation Architecture

The following diagram shows how PHP classes are transformed into a GraphQL schema:


Sources: src/App.php121-130


Schema Factory Configuration

The SchemaFactory is initialized in the Light\App constructor and configured with namespace discovery, custom type mappers, and service integrations:


The initialization sequence:

  1. Server Creation (src/App.php121): Creates Light\GraphQL\Server with caching configuration based on mode (dev/prod)
  2. Cache Configuration (src/App.php104-119): Sets cache lifetime (15 seconds in dev, 0 in prod for no caching during development)
  3. Factory Retrieval (src/App.php124): Obtains the SchemaFactory instance from the server
  4. Namespace Registration (src/App.php125): Adds the Light namespace for auto-discovery
  5. Type Mapper Addition (src/App.php126): Registers custom TypeMapperFactory for database types
  6. Auth Integration (src/App.php529-530): Connects authentication and authorization services

Sources: src/App.php59-147 src/App.php500-537


Type Declaration with Attributes

GraphQLite uses PHP 8 attributes to declare GraphQL types and fields. The framework scans classes for these attributes to build the schema:

Core Type Attributes

AttributePurposeApplied ToExample Location
#[Type]Declares a GraphQL object typeClassessrc/Type/App.php28
#[Field]Declares a field on a typeMethodssrc/Type/App.php32
#[Query]Declares a root query fieldMethodsUsed in controllers
#[Mutation]Declares a root mutation fieldMethodsUsed in controllers

Parameter Attributes

AttributePurposeExample Location
#[Autowire]Injects service from containersrc/Type/App.php100
#[InjectUser]Injects authenticated usersrc/Type/App.php143
#[Logged]Requires authenticationsrc/Type/App.php99
#[Right("permission")]Requires permissionsrc/Type/App.php340

Type Declaration Example

The Light\Type\App class demonstrates type declaration:


Sources: src/Type/App.php28-541


Type Mapping System

The type mapping system converts between PHP types and GraphQL types. GraphQLite provides default mappings, which are extended by custom type mappers:

Default Type Mappings


Output Type Overrides

Methods can specify custom GraphQL output types using the outputType parameter:

PHP Return TypeoutputType ParameterGraphQL Type
array"mixed"Generic JSON scalar
array"[mixed]"List of mixed values
array"[String]"List of strings
\Light\Db\Query(auto-detected)Paginated result type

Examples from src/Type/App.php:

  • Line 38: outputType: "mixed" for dynamic array structure
  • Line 57: outputType: "[mixed]" for list of dynamic objects
  • Line 81: outputType: "[String]" for string array
  • Line 196: outputType: "mixed" for menu structure

Sources: src/Type/App.php38 src/Type/App.php57 src/Type/App.php81 src/Type/App.php196


Custom Type Mappers for Database Types

The framework adds a custom type mapper specifically for handling Light\Db\Query objects, which represent database queries that need special GraphQL type handling:


Query Type Examples

Methods returning Light\Db\Query are automatically converted to paginated GraphQL types:

These methods enable pagination, filtering, and sorting through the GraphQL API automatically.

Sources: src/App.php126 src/Type/App.php414-540


Namespace Discovery and Controller Registration

The schema factory discovers types and resolvers by scanning registered namespaces for annotated classes:


Discovery Process

  1. Namespace Registration: addNamespace("Light") at src/App.php125
  2. Composer Autoloader Integration: Uses ComposerFinder to locate classes
  3. Attribute Scanning: Reflection API reads PHP 8 attributes
  4. Type Building: Creates GraphQL types from discovered classes
  5. Schema Assembly: Combines all types into complete schema

The framework also discovers permissions from these namespaces during RBAC initialization (src/App.php392-472), scanning for #[Right] attributes.

Sources: src/App.php125 src/App.php392-472


Mixed Type Support

For dynamic data structures that don't fit standard GraphQL types, the framework supports a mixed scalar type through the mathsgod/graphqlite-mixed-type package:

Mixed Type Usage Patterns

Use CaseDeclarationExample
Dynamic objectoutputType: "mixed"Menu configuration, 2FA response
Array of dynamic objectsoutputType: "[mixed]"Custom field schemas
Flexible inputReturn arrayConfiguration values

Examples from Type\App

  1. 2FA Secret Generation (src/Type/App.php38-53):

    
    

    Returns structure: {secret: string, host: string, image: string}

  2. Custom Field Schemas (src/Type/App.php57-67):

    
    

    Returns array of FormKit schema objects

  3. Menu Structure (src/Type/App.php196-260):

    
    

    Returns nested menu array with dynamic properties

  4. Filesystem List (src/Type/App.php497-505):

    
    

    Returns filesystem configurations as JSON

Sources: src/Type/App.php38 src/Type/App.php57 src/Type/App.php196 src/Type/App.php497 composer.lock1974-2012


Schema Caching and Performance

The schema generation process is cached to avoid expensive reflection and introspection on every request:

Cache Configuration


Cache Behavior

  • Development Mode (src/App.php112-115):

    • Cache lifetime: 15 seconds
    • Debug enabled
    • Schema refreshes frequently for rapid development
  • Production Mode (src/App.php109-111):

    • Cache lifetime: 0 (permanent until cache clear)
    • Debug disabled
    • Maximum performance, schema frozen

The cache is retrieved from the GraphQL server at src/App.php123 and stored in $this->cache for application use.

Schema Generation Execution

The actual schema generation occurs lazily when createSchema() is called (src/App.php577):


This happens in the execute() method, which is called per GraphQL request. The schema is cached after first generation, so subsequent requests use the cached version.

Sources: src/App.php104-124 src/App.php567-579 composer.lock3804-3902


Integration with Authentication and Authorization

The schema factory integrates with the authentication and authorization system to enable declarative security on GraphQL fields:

Service Integration

At request processing time (src/App.php526-534), the factory is configured with security services:


This enables two key annotations:

  1. #[Logged]: Requires authenticated user (enforced by authentication service)
  2. #[Right("permission")]: Requires specific permission (enforced by authorization service)

Security Enforcement Flow


Examples of protected fields:

Sources: src/App.php526-537 src/Type/App.php99 src/Type/App.php340 src/Type/App.php413