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 example
<?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 example
<?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 example
<?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 example
<?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 /graphql as GraphQL.
  • Classify service-style operation names such as ProductService.GetProduct as gRPC.
  • Classify action-style POST endpoints such as /cancelOrder as RPC.
  • Treat ordinary resource paths such as /v1/products/123 as 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 example
<?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.