Extending the schema
- Adding a custom model
- Add a new class-backed type beyond DataObject
- Adding a custom operation
- Add a new operation for model types
- Adding middleware
- Add middleware to to extend query execution
- The global schema
- How to push modifications to every schema in the project
Adding middleware
Middleware is any piece of functionality that is interpolated into a larger process. A key feature of middleware is that it can be used with other middlewares in sequence and not have to worry about the order of execution.
In silverstripe/graphql
, middleware is used for query execution,
but could ostensibly be used elsewhere too if the API ever accomodates
such an expansion.
The middleware API in the silverstripe/graphql
module is separate from other common middleware
APIs in Silverstripe CMS, such as HTTPMiddleware
. The two are not interchangable.
The signature for middleware (defined in QueryMiddleware
) looks like this:
use GraphQL\Type\Schema;
public abstract function process(Schema $schema, string $query, array $context, array $vars, callable $next);
The return value should be ExecutionResult
or an array
.
$schema
: The underlying Schema object. Useful to inspect whether types are defined in a schema.$query
: The raw query string.$context
: An arbitrary array which holds information shared between resolvers. Use implementors ofContextProvider
to get and set data, rather than relying on the array keys directly.$vars
: An array of (optional) Query Variables.$next
: A callable referring to the next middleware in the chain
Let's write a simple middleware that logs our queries as they come in.
namespace App\GraphQL\Middleware;
use GraphQL\Type\Schema;
use SilverStripe\GraphQL\Middleware\QueryMiddleware;
use SilverStripe\GraphQL\QueryHandler\UserContextProvider;
// ...
class LoggingMiddleware implements QueryMiddleware
{
public function process(Schema $schema, string $query, array $context, array $vars, callable $next)
{
$member = UserContextProvider::get($context);
Injector::inst()->get(LoggerInterface::class)
->info(sprintf(
'Query executed: %s by %s',
$query,
$member ? $member->Title : '<anonymous>';
));
// Hand off execution to the next middleware
return $next($schema, $query, $context, $vars);
}
}
Now we can register the middleware with our query handler:
SilverStripe\Core\Injector\Injector:
SilverStripe\GraphQL\QueryHandler\QueryHandlerInterface.default:
class: SilverStripe\GraphQL\QueryHandler\QueryHandler
properties:
Middlewares:
logging: '%$App\GraphQL\Middleware\LoggingMiddleware'