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