PHP - Creating GraphQL APIs with PHP
Introduction
GraphQL is a modern API query language developed by Facebook that provides a flexible and efficient way for clients to request data from a server. Unlike REST APIs, where each endpoint returns a predefined set of data, GraphQL allows clients to specify exactly what data they need. This reduces unnecessary data transfer and improves application performance.
PHP developers can build GraphQL APIs using libraries such as webonyx/graphql-php, Lighthouse (for Laravel), or Overblog GraphQL Bundle (for Symfony). GraphQL is widely used in web applications, mobile apps, dashboards, and enterprise systems where efficient data retrieval is important.
For example, an e-commerce application can use a GraphQL API to fetch product details, customer information, reviews, and inventory status in a single request instead of calling multiple REST endpoints.
Why Use GraphQL Instead of REST?
Traditional REST APIs expose multiple endpoints.
Example:
-
/users -
/products -
/orders -
/categories
To display a user's dashboard, the frontend may need to call several endpoints one after another.
GraphQL uses a single endpoint.
Example:
/graphql
The client sends a query specifying exactly what information it wants.
Benefits include:
-
Reduced network requests
-
Faster response times
-
Flexible data retrieval
-
Easier API evolution
-
Better support for mobile applications
-
Reduced over-fetching and under-fetching
Installing GraphQL in PHP
One of the most popular GraphQL libraries for PHP is:
webonyx/graphql-php
Install it using Composer.
composer require webonyx/graphql-php
This package provides everything required to create GraphQL schemas, queries, mutations, and execute requests.
Understanding GraphQL Components
A GraphQL API consists of several important components.
1. Schema
The schema defines the structure of the API.
It specifies:
-
Data types
-
Available queries
-
Available mutations
-
Relationships
Example schema concept:
Product
id
name
price
Customer
id
name
email
Order
id
total
The schema acts as a contract between the server and clients.
2. Types
Types define objects in the GraphQL API.
Example:
Product
ID
Name
Price
Description
Category
PHP representation:
ProductType
Each field has a specific data type.
ID
String
Int
Float
Boolean
Custom object types can also be created.
3. Queries
Queries retrieve data.
Example GraphQL query:
{
products {
id
name
price
}
}
Unlike REST, only requested fields are returned.
Example response:
{
"data": {
"products": [
{
"id":1,
"name":"Laptop",
"price":55000
}
]
}
}
4. Mutations
Mutations perform operations like:
-
Insert
-
Update
-
Delete
Example:
mutation {
createProduct(
name:"Phone",
price:25000
){
id
name
}
}
Response:
{
"data":{
"createProduct":{
"id":12,
"name":"Phone"
}
}
}
5. Resolvers
Resolvers contain the actual PHP logic.
Whenever a query requests data, GraphQL calls a resolver.
Example:
GraphQL Query
↓
Resolver
↓
Database
↓
Response
Example resolver:
function getProducts()
{
return Product::all();
}
Resolvers can:
-
Read database records
-
Validate data
-
Call APIs
-
Process business logic
Building a Simple Product API
Suppose a store has products.
Database table:
products
| id | name | price |
|---|---|---|
| 1 | Laptop | 55000 |
| 2 | Phone | 25000 |
The GraphQL schema defines:
Product
id
name
price
Clients can request:
{
products{
id
name
price
}
}
The PHP resolver fetches records.
$products = Product::all();
The response contains only requested fields.
Fetching a Single Product
GraphQL query:
{
product(id:1){
name
price
}
}
Resolver:
function getProduct($id)
{
return Product::find($id);
}
Response:
{
"data":{
"product":{
"name":"Laptop",
"price":55000
}
}
}
Nested Queries
GraphQL supports nested objects.
Example:
Customer
↓
Orders
↓
Products
Single query:
{
customer(id:2){
name
orders{
total
products{
name
price
}
}
}
}
Instead of multiple REST calls, everything is fetched together.
Query Arguments
Queries accept parameters.
Example:
{
products(category:"Electronics"){
name
price
}
}
PHP resolver:
function getProducts($category)
{
return Product::where(
"category",
$category
)->get();
}
Arguments help filter data.
Pagination
Large datasets should not be returned all at once.
Example:
{
products(page:1, limit:10){
id
name
}
}
PHP:
Product::limit(10)
->offset(0)
->get();
Pagination improves performance.
Sorting
Example:
{
products(sort:"price"){
name
price
}
}
Result:
Phone
Tablet
Laptop
Sorting helps organize data.
Filtering
Example:
{
products(
category:"Electronics",
priceGreaterThan:10000
){
name
price
}
}
Filtering returns only relevant records.
Creating Data with Mutations
Example:
mutation{
createProduct(
name:"Keyboard",
price:1200
){
id
name
}
}
PHP:
$product = Product::create([
"name"=>"Keyboard",
"price"=>1200
]);
Response:
{
"data":{
"createProduct":{
"id":15,
"name":"Keyboard"
}
}
}
Updating Records
Mutation:
mutation{
updateProduct(
id:2,
price:28000
){
id
price
}
}
PHP:
$product = Product::find(2);
$product->price = 28000;
$product->save();
Deleting Records
Mutation:
mutation{
deleteProduct(id:3)
}
PHP:
Product::destroy(3);
GraphQL Variables
Instead of hardcoding values:
id:5
Variables are used.
Query:
query Product($id:ID!){
product(id:$id){
name
price
}
}
Variables:
{
"id":5
}
Variables improve security and code reuse.
Authentication
GraphQL APIs should verify user identity before processing sensitive requests.
Common authentication methods include:
-
JSON Web Tokens (JWT)
-
OAuth 2.0
-
Laravel Sanctum
-
Laravel Passport
-
Session-based authentication
Example workflow:
User Login
↓
Token Generated
↓
Client Stores Token
↓
Every GraphQL Request Includes Token
↓
Server Validates Token
Unauthorized requests should be rejected.
Authorization
Authentication confirms who the user is, while authorization determines what they are allowed to do.
Example:
-
Customers can view only their own orders.
-
Administrators can create, update, and delete products.
-
Vendors can manage only their own inventory.
Resolvers should verify permissions before executing operations.
Error Handling
GraphQL returns errors in a structured format.
Example:
{
"errors":[
{
"message":"Product not found"
}
]
}
Developers should avoid exposing sensitive information such as SQL queries or server paths in error messages.
Performance Optimization
GraphQL APIs can suffer from performance issues if not optimized.
Common techniques include:
DataLoader
DataLoader batches and caches database requests to prevent the "N+1 query problem."
Without DataLoader:
100 Products
↓
100 Database Queries
With DataLoader:
100 Products
↓
1 Optimized Database Query
Query Complexity Limits
Restrict deeply nested or expensive queries to prevent abuse.
Response Caching
Cache frequently requested data using tools like Redis or Memcached to reduce database load.
Pagination
Always paginate large collections instead of returning all records.
Database Indexing
Ensure frequently filtered or sorted columns are indexed for faster query execution.
GraphQL Security Best Practices
-
Validate all user input before processing.
-
Implement authentication and authorization for protected operations.
-
Disable unnecessary introspection in production if appropriate.
-
Limit query depth and complexity to prevent denial-of-service attacks.
-
Use HTTPS to encrypt data in transit.
-
Sanitize data before storing it in the database.
-
Log suspicious requests and monitor API usage.
-
Apply rate limiting to prevent abuse.
GraphQL vs REST
| Feature | GraphQL | REST |
|---|---|---|
| Endpoints | Single endpoint | Multiple endpoints |
| Data Fetching | Client specifies required fields | Server returns predefined data |
| Over-fetching | Avoided | Common |
| Under-fetching | Avoided | Possible |
| Versioning | Typically unnecessary due to schema evolution | Often requires API versioning |
| Nested Data | Supported in one request | Usually requires multiple requests |
| Flexibility | High | Moderate |
Real-World Applications
GraphQL APIs built with PHP are commonly used in:
-
E-commerce platforms for products, customers, carts, and orders.
-
Social networking applications to efficiently retrieve user profiles, posts, comments, and followers.
-
Learning Management Systems (LMS) to manage courses, lessons, quizzes, and student progress.
-
Content Management Systems (CMS) for articles, categories, authors, and media assets.
-
Banking and financial dashboards that aggregate account details, transactions, and analytics.
-
Healthcare portals for securely accessing patient records, appointments, prescriptions, and reports.
-
Enterprise Resource Planning (ERP) systems for inventory, procurement, sales, and employee management.
-
Mobile applications that require optimized data usage and reduced network requests.
Conclusion
GraphQL provides a powerful and flexible approach to building APIs in PHP by allowing clients to request only the data they need through a single endpoint. With well-designed schemas, efficient resolvers, secure authentication, optimized queries, and proper error handling, PHP developers can create scalable, high-performance APIs for modern web and mobile applications. As applications grow in complexity, GraphQL offers significant advantages over traditional REST APIs by improving efficiency, reducing network traffic, and simplifying data access across multiple interconnected resources.