GraphQL APIs in PHP

GraphQL is a query language for APIs that lets clients ask for exactly the data they need from a single endpoint. In this lesson you'll design a typed schema , write queries and mutations , back fields with resolvers using webonyx/graphql-php , and see why it solves REST's over- and under-fetching.

Learn GraphQL APIs in PHP in our free PHP course — an interactive lesson with worked examples, a practice exercise and a quick reference.

Part of the free Php course at LearnCodingFast — hands-on lessons with examples you run in your browser, plus practice exercises and a quick quiz.

What You'll Learn in This Lesson

1️⃣ The Schema: A Typed Contract

Everything in GraphQL starts with the schema , written in the Schema Definition Language (SDL) . It declares your types (like User and Post ), their fields, and the relationships between them. Two special types are the entry points: Query lists every read operation, and Mutation lists every write. A trailing ! marks a field as non-nullable. Because the schema is typed, the server can validate any incoming query before running a line of resolver code.

This one document is the whole API's contract. It also self-documents: tools can read it to give clients autocompletion and validation, which is a big part of GraphQL's appeal.

2️⃣ Queries: Reading Exactly What You Need

A query reads data. The client writes the shape it wants — which fields, and how deep — and the server returns JSON in exactly that shape. Ask for three fields and you get three fields; ask for nested posts and they come back inside the user. This is the heart of GraphQL: the client controls the response shape, so there are no wasted bytes and no second request for related data.

Notice how the response mirrors the request one-to-one. That predictability makes GraphQL responses easy to consume on the client.

3️⃣ Mutations: Changing Data

Reads use queries; anything that changes data uses a mutation — creating, updating, or deleting. The syntax is nearly identical, but the operation keyword is mutation , and it maps to a field on the special Mutation type. Usefully, a mutation returns data too: you pick which fields of the newly changed object to read back, so a create can immediately hand you the new id .

Keeping reads (queries) and writes (mutations) separate is a clear, enforced convention — the schema makes it impossible to accidentally mutate data from a query.

4️⃣ Resolvers: Where PHP Does the Work

A schema describes what is possible; resolvers implement how . Every field is backed by a resolver function that returns its value — usually by reading a database, calling a service, or following a relationship. In PHP the standard engine is webonyx/graphql-php ( composer require webonyx/graphql-php ): you define types and their resolve callbacks, build a Schema , and call GraphQL::executeQuery() with the incoming query.

For Laravel, Lighthouse builds on this engine with a schema-first, directive-driven style so you write far less of this wiring by hand — but knowing the raw resolver model first means you understand what it's doing.

5️⃣ Why GraphQL? Over- and Under-Fetching

The clearest reason to reach for GraphQL is the data-fetching problem REST runs into. With REST, each endpoint returns a fixed shape : a screen that needs a user plus their posts plus comments often means several requests ( under-fetching ), while an endpoint that returns every field forces clients to download data they'll never show ( over-fetching ). GraphQL collapses that into one request against one endpoint, returning precisely the fields asked for.

Now you try the two core skills — finishing a schema and writing a query. Fill in each ___ using the 👉 hint, then check it against the Output panel.

One more. Write the smallest possible query that asks for just one field.

Common Errors (and the fix)

Pro Tips

📋 Quick Reference — GraphQL in PHP

Concept / Snippet

What It Means

type User

Define an object type in SDL

String!

A non-nullable (required) field

type Query

Root type listing all read operations

type Mutation

Root type listing all write operations

query

Read data, choosing exact fields

mutation

Create, update, or delete data

resolve => fn(...)

Function that returns a field's value

webonyx/graphql-php

Core PHP GraphQL server engine

Lighthouse

Schema-first GraphQL for Laravel

Frequently Asked Questions

Mini-Challenge: A GraphQL Todo API

No code is filled in this time — just a brief and an outline. Build it with webonyx/graphql-php : define a Todo type, a query that lists todos, and a mutation that adds one, then wire the single endpoint. This is the full read-and-write GraphQL loop you'll use in real services.

🎉 Lesson Complete!

Practice quiz

How many HTTP endpoints does a typical GraphQL API expose?

  • One endpoint for everything (usually /graphql)
  • One per resource, like REST
  • Two: one read, one write
  • One per field

Answer: One endpoint for everything (usually /graphql). GraphQL exposes a single endpoint. The client describes exactly what it wants in the request body, rather than hitting many resource URLs.

In GraphQL, what is a 'query' used for?

  • Defining the schema
  • Creating new data
  • Reading (fetching) data
  • Deleting data

Answer: Reading (fetching) data. A query reads data. Operations that change data (create, update, delete) are mutations.

Which operation type changes data on the server?

  • fragment
  • mutation
  • subscription
  • query

Answer: mutation. Mutations create, update, or delete data. Queries are read-only by convention.

What is a resolver?

  • A caching layer
  • The HTTP router
  • A database table
  • A function that returns the value for a field

Answer: A function that returns the value for a field. Each field is backed by a resolver function that produces its value, often by reading a database or calling another service.

What problem does GraphQL solve compared to REST?

  • Over-fetching and under-fetching of data
  • It makes PHP run faster
  • It removes the need for a database
  • It encrypts traffic automatically

Answer: Over-fetching and under-fetching of data. REST endpoints return fixed shapes, causing over-fetching (too much) or under-fetching (needing multiple round trips). GraphQL lets the client request exactly the fields it needs.

Which PHP library is the de-facto core engine for building GraphQL servers?

  • symfony/console
  • webonyx/graphql-php
  • phpunit/phpunit
  • guzzlehttp/guzzle

Answer: webonyx/graphql-php. webonyx/graphql-php is the reference PHP implementation of the GraphQL spec, and most higher-level tools build on it.

Which package is the popular GraphQL solution specifically for Laravel?

  • Eloquent
  • Blade
  • Horizon
  • Lighthouse

Answer: Lighthouse. Lighthouse lets you build a GraphQL server in Laravel using a schema-first, directive-driven approach on top of webonyx/graphql-php.

What is the SDL in GraphQL?

  • A database driver
  • A query caching protocol
  • The Schema Definition Language used to describe types and fields
  • A PHP extension

Answer: The Schema Definition Language used to describe types and fields. The Schema Definition Language (SDL) is the typed, human-readable syntax for declaring object types, fields, queries, and mutations.

In the type 'type User { id: ID! name: String! }', what does the '!' mean?

  • The field is private
  • The field is non-nullable (required)
  • The field is deprecated
  • The field is a list

Answer: The field is non-nullable (required). A trailing ! marks a field as non-nullable: the server guarantees it will always return a value of that type.

Why is GraphQL strongly typed via its schema?

  • So the schema documents the API and validates every query before execution
  • To replace the need for HTTPS
  • So clients can skip authentication
  • To slow down responses

Answer: So the schema documents the API and validates every query before execution. The typed schema is a contract: it self-documents the API, powers tooling and autocompletion, and lets the server validate a query's shape before any resolver runs.

Continue this course

Related lessons