GraphQL

GraphQL is a query language for APIs. Instead of fixed REST endpoints, clients ask for exactly the fields they need. LacePHP includes a simple GraphQL endpoint and schema builder so you can add GraphQL support without extra libraries.

Why GraphQL Matters

  • Fetch exactly what you need: no over- or under-fetching of data

  • Single endpoint: one URL handles all queries

  • Strong typing: schema defines available queries and types, catching errors early

Exposing the Endpoint

Add this route (e.g. in routes/api.php):

use Lacebox\Heel\GraphQLEndpoint;

$router->addRoute(
    'POST',
    '/graphql',
    [GraphQLEndpoint::class, 'execute']
);

Clients send a POST with JSON body:

{
  "query": "query($n: String){ hello, greet(name:$n) }",
  "variables": { "n": "Alice" }
}

Response is JSON:

{
  "data": {
    "hello": "Hello from lacePHP GraphQL!",
    "greet": "Hello, Alice"
  }
}

Defining the Schema

LacePHP builds a schema with a default field:

  • hello: returns “Hello from lacePHP GraphQL!”

On PHP 8+, you can add fields via attributes. Create weave/GraphQL/GreetField.php:

<?php
namespace Weave\GraphQL;

use Lacebox\Tongue\Attributes\GraphQLField;
use GraphQL\Type\Definition\Type;

#[GraphQLField(
    name: 'greet',
    type: Type::string(),
    resolver: fn($_, array $args) => "Hello, {$args['name']}!"
)]
class GreetField {}

When building, LacePHP scans weave/GraphQL/*.php for #[GraphQLField] and merges them into the root Query type.

Advanced Example

Add a “double” field in weave/GraphQL/DoubleField.php:

<?php
namespace Weave\GraphQL;

use Lacebox\Tongue\Attributes\GraphQLField;
use GraphQL\Type\Definition\Type;

#[GraphQLField(
    name: 'double',
    type: Type::int(),
    resolver: fn($_, array $args) => $args['value'] * 2
)]
class DoubleField {}

Query:

query($v: Int!) {
  double(value: $v)
}

Response:

{
  "data": {
    "double": 84
  }
}

How It Works

  • GraphQLEndpoint::execute() - Only accepts POST; rejects others with 405 - Reads query, variables, operationName from request body - Builds schema via GraphQLSchema::build() - Executes query and outputs JSON

  • GraphQLSchema::build() - Defines base fields (hello) - On PHP 8+, loads attribute-driven fields from weave/GraphQL - Returns a Schema instance for execution

Best Practices

  • Use a GraphQL IDE (GraphiQL, Playground) to explore and validate your schema

  • Keep resolvers lean; delegate heavy logic to services or models

  • Always use variables for user input to prevent injection and enable caching

  • Secure the /graphql endpoint with CORS and authentication middleware

Warning

  • Complex nested queries can be expensive; consider depth limits or query complexity analysis

  • Only expose fields you intend users to see; design your schema carefully

  • Handle exceptions and format errors to avoid leaking sensitive information