Building a Basic GraphQL Schema
Learn How to Build a Basic GraphQL Schema
What is GraphQL?
GraphQL is an alternative to REST and other API systems that, in essence, convert your application into a graph database that you can query against.
Instead of exposing and hand-crafting the specific endpoints, you can expose the data structures instead.
This approach empowers API consumers like front-end applications and makes it unnecessary to introduce constant changes in the back-end of an application.
For example, let's say you are querying the schema for a few fields:
graphqlquery BlogPosts() { post1: blogPost(slug: "foo") { content } post2: blogPost(slug: "bar") { content } }
Resonance will internally make two database queries in parallel (one for the "foo" blog post and the second one for the "bar" blog post) - similarly to how it would happen with Node.js, Go, or other inherently asynchronous languages.
Basic GraphQL Schema
Let's start with a basic GraphQL schema - one that exposes the ping
object that has a single field: message
which always resolves to "
.
For example, the query:
graphqlquery Ping() { ping1: ping { message } ping2: ping { message } ping3: ping { message } }
Is going to return the following JSON:
json{ "data": { "ping1": { "message": "pong" }, "ping2": { "message": "pong" }, "ping3": { "message": "pong" } } }
Exposing the GraphQL Endpoint
Let's create a Responders which handles all the POST
requests issued to the '/graphql' and returns GraphQL responses:
php<?php namespace App\HttpResponder; use App\HttpRouteSymbol; use Distantmagic\Resonance\Attribute\RespondsToHttp; use Distantmagic\Resonance\Attribute\Singleton; use Distantmagic\Resonance\HttpResponder; use Distantmagic\Resonance\HttpResponder\GraphQL as ResonanceGraphQL; use Distantmagic\Resonance\HttpResponderInterface; use Distantmagic\Resonance\RequestMethod; use Distantmagic\Resonance\SingletonCollection; use Distantmagic\Resonance\SiteAction; use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ServerRequestInterface; #[RespondsToHttp( method: RequestMethod::POST, pattern: '/graphql', routeSymbol: HttpRouteSymbol::GraphQL, )] #[Singleton(collection: SingletonCollection::HttpResponder)] final readonly class GraphQL extends HttpResponder { public function __construct(private ResonanceGraphQL $graphql) {} public function respond(ServerRequestInterface $request, ResponseInterface $response): HttpResponderInterface { return $this->graphql; } }
The Ping Object Type
Resonance's GraphQL implementation uses the webonyx/graphql-php library internally to build schemas so that we will follow their object type format.
We will use a Closure
to resolve the ping
field value:
php<?php namespace App\ObjectType; use Distantmagic\Resonance\Attribute\Singleton; use GraphQL\Type\Definition\ObjectType; use GraphQL\Type\Definition\Type; #[Singleton] final class PingType extends ObjectType { public function __construct() { parent::__construct([ 'name' => 'Ping', 'description' => 'Test field', 'fields' => [ 'message' => [ 'type' => Type::string(), 'description' => 'Always responds with pong', 'resolve' => $this->resolvePong(...), ], ], ]); } private function resolvePong(string $rootValue): string { return $rootValue; } }
Building the Root Query
Now that we have a ping
type, we need to assign it to the root GraphQL schema so you can query it.
Just defining the ping
type did nothing yet because GraphQL still doesn't know the name of the field and other necessary details to use that field.
Let's define those now:
php<?php namespace App\GraphQLRootField; use App\ObjectType\PingType; use Distantmagic\Resonance\Attribute\GraphQLRootField; use Distantmagic\Resonance\Attribute\Singleton; use Distantmagic\Resonance\GraphQLFieldableInterface; use Distantmagic\Resonance\GraphQLRootFieldType; use Distantmagic\Resonance\SingletonCollection; #[GraphQLRootField( name: 'ping', type: GraphQLRootFieldType::Query, )] #[Singleton(collection: SingletonCollection::GraphQLRootField)] final readonly class Ping implements GraphQLFieldableInterface { public function __construct(private PingType $pingType) {} public function resolve(): string { return 'pong'; } public function toGraphQLField(): array { return [ 'type' => $this->pingType, 'resolve' => $this->resolve(...), ]; } }
That is it! Now, your project should have the GraphQL schema exposed at the /graphql
URL.
Summary
This tutorial explains how to start with a GraphQL schema with Resonance. If you want to expand this schema, add more Object Types and nest them inside each other. I encourage you to experiment and build a more complex graph.
Comments
If you want to leave a comment Start a discussion on GitHub or join our Community