http clients and apis
REST, RPC, GraphQL, And gRPC Orientation
REST, RPC, GraphQL, and gRPC are different ways to expose operations across a network. PHP developers commonly consume REST and JSON RPC-style APIs, may build or consume GraphQL, and sometimes integrate with gRPC through generated clients or sidecar services.
The goal is not to argue that one style is always best. The useful skill is recognising the style in front of you, understanding its contract, and writing PHP code that handles its request shape, error model, and tooling.
REST
REST-style APIs organise around resources and standard HTTP methods.
<?php
declare(strict_types=1);
$restExamples = [
'list users' => 'GET /v1/users',
'get one user' => 'GET /v1/users/42',
'create user' => 'POST /v1/users',
'replace user' => 'PUT /v1/users/42',
'delete user' => 'DELETE /v1/users/42',
];
foreach ($restExamples as $operation => $request) {
echo $operation . ': ' . $request . PHP_EOL;
}
// Prints:
// get one user: GET /v1/users/42
// create user: POST /v1/users
REST works well for CRUD-style resources, public APIs, and integrations where HTTP status codes, caching, pagination, and OpenAPI documentation are valuable.
RPC
RPC means remote procedure call. The API is organised around actions or commands, often using endpoint names like /calculateTax, /sendInvoice, or /orders.cancel.
<?php
declare(strict_types=1);
function rpcRequest(string $method, array $params): array
{
return [
'jsonrpc' => '2.0',
'method' => $method,
'params' => $params,
'id' => 'req_123',
];
}
echo json_encode(rpcRequest('orders.cancel', ['order_id' => 42]), JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR) . PHP_EOL;
// Prints:
// "method": "orders.cancel"
// "order_id": 42
RPC can be a good fit when the domain is action-heavy and does not map cleanly to resources. The risk is ending up with many inconsistent action names and unclear error handling.
GraphQL
GraphQL lets clients ask for exactly the fields they need from a typed schema. Most GraphQL APIs use a single HTTP endpoint, commonly POST /graphql.
<?php
declare(strict_types=1);
$graphqlRequest = [
'query' => <<<'GRAPHQL'
query Product($id: ID!) {
product(id: $id) {
id
name
price
}
}
GRAPHQL,
'variables' => [
'id' => 'prod_123',
],
];
echo json_encode($graphqlRequest, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR) . PHP_EOL;
// Prints:
// "query": "query Product($id: ID!) ..."
// "id": "prod_123"
GraphQL is useful when clients need flexible data selection, especially across related objects. It also brings different concerns: schema design, resolver performance, query depth, caching, and errors that may appear inside a 200 OK response.
gRPC
gRPC uses service and message definitions, usually written in Protocol Buffers. Instead of hand-writing URLs, clients call generated methods.
service ProductService {
rpc GetProduct (GetProductRequest) returns (Product);
}
In PHP, gRPC usually means generated classes and a runtime extension or client library. It is common in internal service-to-service systems where strict contracts and efficient binary messages matter more than browser readability.
Comparing the styles
<?php
declare(strict_types=1);
function likelyApiStyle(string $requestDescription): string
{
if (str_contains($requestDescription, '/graphql')) {
return 'GraphQL';
}
if (str_contains($requestDescription, 'Service.') || str_contains($requestDescription, 'rpc ')) {
return 'gRPC';
}
if (preg_match('#POST /[a-zA-Z]+[A-Za-z]*$#', $requestDescription)) {
return 'RPC';
}
return 'REST';
}
foreach (['GET /v1/products/123', 'POST /cancelOrder', 'POST /graphql', 'ProductService.GetProduct'] as $request) {
echo $request . ' => ' . likelyApiStyle($request) . PHP_EOL;
}
// Prints:
// GET /v1/products/123 => REST
// POST /cancelOrder => RPC
// POST /graphql => GraphQL
// ProductService.GetProduct => gRPC
This classifier is only illustrative. Real APIs can mix styles.
What to check
Before moving on, make sure you can:
- Recognise resource-oriented REST endpoints.
- Recognise action-oriented RPC endpoints.
- Describe how GraphQL requests and errors differ from REST.
- Explain why gRPC often uses generated client code.
- Choose a reasonable style for simple CRUD, action-heavy workflows, flexible client queries, and internal service calls.
Practice
Practice: Classify API Styles
Write a PHP function that classifies example API operations as REST, RPC, GraphQL, or gRPC.
Requirements
- Accept a method, path, and optional operation name.
- Classify
/graphqlas GraphQL. - Classify service-style operation names such as
ProductService.GetProductas gRPC. - Classify action-style
POSTendpoints such as/cancelOrderas RPC. - Treat ordinary resource paths such as
/v1/products/123as REST. - Return a short reason for the classification.
Show solution
This solution uses simple signals rather than pretending the boundary is always perfect. Many real APIs mix styles.
<?php
declare(strict_types=1);
function classifyApiStyle(string $method, string $path, ?string $operation = null): array
{
if ($operation !== null && preg_match('/^[A-Z][A-Za-z]+Service\.[A-Z][A-Za-z]+$/', $operation)) {
return ['style' => 'gRPC', 'reason' => 'The operation is service-method shaped.'];
}
if ($path === '/graphql') {
return ['style' => 'GraphQL', 'reason' => 'GraphQL commonly uses a single /graphql endpoint.'];
}
if (strtoupper($method) === 'POST' && preg_match('#^/[a-z]+[A-Z][A-Za-z]*$#', $path)) {
return ['style' => 'RPC', 'reason' => 'The endpoint is named like an action.'];
}
return ['style' => 'REST', 'reason' => 'The endpoint is resource-oriented.'];
}
$examples = [
classifyApiStyle('GET', '/v1/products/123'),
classifyApiStyle('POST', '/cancelOrder'),
classifyApiStyle('POST', '/graphql'),
classifyApiStyle('POST', '', 'ProductService.GetProduct'),
];
foreach ($examples as $result) {
echo $result['style'] . ': ' . $result['reason'] . PHP_EOL;
}
// Prints:
// REST: The endpoint is resource-oriented.
// RPC: The endpoint is named like an action.
// GraphQL: GraphQL commonly uses a single /graphql endpoint.
// gRPC: The operation is service-method shaped.
The classification helps you ask the next questions: where is the contract documented, how are errors represented, and whether the client code is handwritten or generated.