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`): .. code-block:: php use Lacebox\Heel\GraphQLEndpoint; $router->addRoute( 'POST', '/graphql', [GraphQLEndpoint::class, 'execute'] ); Clients send a POST with JSON body: .. code-block:: json { "query": "query($n: String){ hello, greet(name:$n) }", "variables": { "n": "Alice" } } Response is JSON: .. code-block:: 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`: .. code-block:: php "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`: .. code-block:: php $args['value'] * 2 )] class DoubleField {} Query: .. code-block:: graphql query($v: Int!) { double(value: $v) } Response: .. code-block:: json { "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 | |