GraphQL API with PHP: Step-by-Step Practical Tutorial
GraphQL is a query language for APIs that allows clients to receive only the data they actually need. Unlike REST, where each endpoint returns a fixed structure, GraphQL provides flexibility and efficiency. In this tutorial, we will create a full-fledged GraphQL API in PHP from scratch — from library installation to handling queries and mutations.
Why GraphQL and PHP are a Great Pair?
PHP remains one of the most popular languages for server-side development. Using the webonyx/graphql-php library, you can easily integrate GraphQL into any project — from a simple blog to a complex CRM. Key advantages:
- Query flexibility — the client decides which fields to receive.
- Single entry point — instead of multiple endpoints, one
/graphql. - Strong typing — the schema defines all types and relationships.
- Frontend convenience — React, Vue and other frameworks work easily with GraphQL.
Step-by-Step Implementation of GraphQL API in PHP
1. Environment Setup and Installation
First, let's create a new project and install the main library via Composer:
composer require webonyx/graphql-phpWe will also need a PSR-7 compatible HTTP handler. We'll use guzzlehttp/psr7 and nyholm/psr7-server:
composer require guzzlehttp/psr7 nyholm/psr7-serverLet's create the basic folder structure:
project/├── src/│ ├── Schema/│ ├── Resolvers/│ └── Types/├── public/│ └── index.php├── vendor/└── composer.json2. Defining the GraphQL Schema
The schema is the heart of the GraphQL API. It describes data types and available operations. Let's create the file src/Schema/Schema.php:
<?phpnamespace App\\Schema;
use GraphQL\\Type\\Definition\\ObjectType;use GraphQL\\Type\\Definition\\Type;use GraphQL\\Type\\Schema as GraphQLSchema;
class Schema{ public static function build(): GraphQLSchema { // "User" type $userType = new ObjectType([ 'name' => 'User', 'fields' => [ 'id' => Type::int(), 'name' => Type::string(), 'email' => Type::string(), ] ]);
// "Query" type — root query $queryType = new ObjectType([ 'name' => 'Query', 'fields' => [ 'user' => [ 'type' => $userType, 'args' => [ 'id' => Type::nonNull(Type::int()) ], 'resolve' => function ($root, $args) { // Resolver will be here return UserResolver::getUser($args['id']); } ], 'users' => [ 'type' => Type::listOf($userType), 'resolve' => function () { return UserResolver::getAllUsers(); } ] ] ]);
// "Mutation" type — root mutation $mutationType = new ObjectType([ 'name' => 'Mutation', 'fields' => [ 'createUser' => [ 'type' => $userType, 'args' => [ 'name' => Type::nonNull(Type::string()), 'email' => Type::nonNull(Type::string()) ], 'resolve' => function ($root, $args) { return UserResolver::createUser($args['name'], $args['email']); } ] ] ]);
return new GraphQLSchema([