xaddax / webonyx-psr15-middleware
PSR-15 middleware for webonyx/graphql-php
Requires
- php: ^8.3 || ^8.4
- ext-mbstring: *
- psr/cache: ^3.0
- psr/container: ^2.0
- psr/http-factory: ^1.0
- psr/http-message: ^2.0
- psr/http-server-middleware: ^1.0
- psr/log: ^3.0
- webonyx/graphql-php: ^15.0.0
Requires (Dev)
- mikey179/vfsstream: ^1.6
- nyholm/psr7: ^1.8
- phpstan/phpstan: ^1.10
- phpunit/phpunit: ^11.0
- squizlabs/php_codesniffer: ^3.9
- symfony/cache: ^7.0
Suggests
- nyholm/psr7: PSR-7 implementation if you don't already have one
- symfony/cache: PSR-6 cache implementation if you don't already have one
README
A framework-agnostic PSR-15 middleware for handling GraphQL requests using webonyx/graphql-php.
Features
- PSR-15 compliant middleware
- Framework agnostic
- Schema caching support
- Request preprocessing capabilities
- Flexible response handling
- Operation-specific resolvers with dependency injection support
- Resolver documentation
Documentation
Installation
composer require xaddax/webonyx-psr15-middleware
Requirements
- PHP 8.3+
- PSR-7 implementation (e.g., nyholm/psr7)
- PSR-17 HTTP factories implementation
- PSR-6 cache implementation (optional, e.g., symfony/cache)
Basic Usage
use GraphQL\Server\ServerConfig; use GraphQL\Type\Schema; use Nyholm\Psr7\Factory\Psr17Factory; use GraphQL\Middleware\Factory\GraphQLMiddlewareFactory; // Create PSR-17 factories $psr17Factory = new Psr17Factory(); // Configure your GraphQL schema and server $serverConfig = new ServerConfig(); $serverConfig->setSchema($schema); // Create the middleware factory $middlewareFactory = new GraphQLMiddlewareFactory( serverConfig: $serverConfig, responseFactory: $psr17Factory, streamFactory: $psr17Factory ); // Create and add the middleware to your application $middleware = $middlewareFactory->createMiddleware();
Schema Generation
The library includes support for generating schemas from .graphql files:
use GraphQL\Middleware\Config\DefaultConfiguration; use GraphQL\Middleware\Factory\GeneratedSchemaFactory; // Configure schema generation $schemaConfig = new DefaultConfiguration([ 'schema' => [ 'directories' => [__DIR__ . '/schema'], 'parser_options' => [], ], 'cache' => [ 'enabled' => true, 'directory' => __DIR__ . '/cache', ], ]); // Create schema factory $schemaFactory = new GeneratedSchemaFactory($schemaConfig); $schema = $schemaFactory->createSchema();
Framework Integration
Slim 4
use Slim\Factory\AppFactory; $app = AppFactory::create(); $app->add($middlewareFactory->createMiddleware());
Mezzio
use Mezzio\Application; $app = new Application(); $app->pipe($middlewareFactory->createMiddleware());
Laravel
use Illuminate\Support\ServiceProvider; class GraphQLServiceProvider extends ServiceProvider { public function boot() { $middleware = $this->app->make(GraphQLMiddlewareFactory::class) ->createMiddleware(); $this->app['router']->middleware('graphql', $middleware); } }
Request Preprocessing
You can add authentication/authorization by implementing the RequestPreprocessorInterface
:
use GraphQL\Middleware\RequestPreprocessorInterface; class AuthPreprocessor implements RequestPreprocessorInterface { public function process(ServerRequestInterface $request): ServerRequestInterface { $token = $request->getHeaderLine('Authorization'); if (!$this->isValidToken($token)) { throw new UnauthorizedException('Invalid token'); } return $request; } } // Add to middleware factory $middlewareFactory = new GraphQLMiddlewareFactory( serverConfig: $serverConfig, responseFactory: $psr17Factory, streamFactory: $psr17Factory, requestPreprocessor: new AuthPreprocessor() );
Development
Code Quality
The project uses PHP_CodeSniffer for coding standards and PHPStan for static analysis.
To check coding standards:
composer cs-check
To automatically fix coding standards:
composer cs-fix
To run static analysis:
composer stan
To run all checks (coding standards, static analysis, and tests):
composer check
Testing
To run the test suite:
composer test
Examples
Check the examples/
directory for complete working examples with different frameworks:
examples/slim/
- Slim 4 integrationexamples/mezzio/
- Mezzio integrationexamples/laravel/
- Laravel integration
License
MIT License. See LICENSE file for details.
==========================
To use the middleware in Laminas Mezzio, configure the factories
in config/autoload/dependencies.global.php
return [ 'dependencies' => [ 'factories' => [ \GraphQL\Server\StandardServer::class => \Xaddax\GraphQL\Factory\StandardServerFactory::class, \GraphQL\Middleware\GraphQLMiddleware::class => \Xaddax\GraphQL\Factory\GraphQLMiddlewareFactory::class, ], ], ];
Add configuration in config/autoload/graphql.global.php
return [ 'graphQL' => [ 'middleware' => [ 'allowedHeaders' => [ 'application/graphql', 'application/json', ], ], 'schema' => \Path\To\Schema::class, // optional, defaults to webonyx Schema 'schemaConfig' => [], // optional, if not configured expected in Schema class constructor 'server' => \Path\To\Server::class, // not yet implemented, defaults to webonyx StandardServer 'serverConfig' => [ 'context' => \GraphQL\Context\TokenContext::class 'schema' => \Path\To\Your\Schema::class, ], ], ];
see the WebOnyx Server Configuration Documentation for the full options for the server config.
You'll need to set up the route. In config/routes.php
return function (Application $app, MiddlewareFactory $factory, ContainerInterface $container) : void { $app->post('/graphql', \GraphQL\Middleware\GraphQLMiddleware::class, 'graphql'); };
Schema Definition Language
You can also use a Schema Definition Language as discussed in the webonyx documentation.
In config/autoload/graphql.global.php
change the schema in the serverConfig
to generatedSchema
return [ 'graphQL' => [ 'serverConfig' => [ 'schema' => 'generatedSchema', ], ], ];
Then inside of the graphQL
config add the generatedSchema
configuration
return [ 'graphQL' => [ 'generatedSchema' => [ 'parserOptions' => [ 'experimentalFragmentVariables' => true, // to parse fragments 'noLocation' => false, // default, set true for development ], 'cache' => [ 'alwaysEnabled' => false, // default, set to true to cache when the system cache is not enabled 'directoryChangeFilename' => 'directory-change-cache.php', // default 'schemaCacheFilename' => 'schema-cache.php', // default ], 'schemaDirectories' => [ '/full/path/to/schema-directory-1', '/full/path/to/schema-directory-2', ], ], ], ];
See the documentation for
parserOptions
The cached data is stored in data/cache/graphql
.