GraphQLite derives a GraphQL schema from PHP attributes on your classes
Use PHP Attributes to declare your GraphQL API
At a glance
- What is it?
- GraphQLite is a GraphQL library for PHP that lets you declare types, fields, queries and mutations with PHP attributes on ordinary controller and entity classes, with optional Symfony and Laravel integrations. It suits a PHP team that wants a typed GraphQL layer without a separate schema definition file, and it is a PHP 8 feature dependency rather than a drop-in for any PHP version.
- Who is it for?
- Adopt GraphQLite when your PHP application already has the domain objects and you want the GraphQL schema to live in the same classes rather than in a separate schema file, and pick a schema-first library if your client team owns the contract.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 4 days ago.
- What is it written in?
- Mainly MDX, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 22, 2026, and from our analysis. They are not legal advice.
Editorial analysis
The schema is derived from the classes you already have
The library is a GraphQL library for PHP that allows you to use attributes, or annotations, to define your schema and write your queries and mutations using simple-to-write controllers. The central idea is that there is no separate schema file to keep in sync. A GraphQL API can be created by simply annotating your PHP classes, and the feature list claims you can create a complete GraphQL API that way. The two halves of the basic example show the shape of it. A controller method carries the Mutation attribute, and an entity class carries the Type attribute, with an Input attribute that says the type can be used as an input, and each exposed property is a Field attribute. The type of the field is derived from the PHP return type, so the PHP type declaration and the GraphQL type are the same declaration. That is the whole value proposition, and the reason it is a pleasant way to work is that the schema cannot drift from the code, because the code is the schema.
A mutation is an attributed method on a plain class
The example is deliberately plain PHP, with no base class to extend and no interface to implement. The controller looks like this:
class ProductController
{
#[Mutation]
public function updateProduct(Product $product): Product
{
// Some code that gets and updates a Product
return $product;
}
}And the entity exposes its fields through attributed accessors:
#[Type]
#[Input(update: true)]
class Product
{
#[Field]
public function getName(): string
{
return $this->name;
}
#[Field]
public function setName(string $name): void
{
$this->name = $name;
}
// ...
}Two details in that snippet carry weight. The Input attribute with the update flag set to true is what makes a type acceptable as a mutation argument, and it is the same type used for output and input, with the attribute deciding the difference. And the accessors are ordinary methods with typed parameters and return types, which means the field types and the mutation argument types are both checked by the PHP type system before GraphQL ever sees them. The query in the README follows directly from the annotations, with the updateProduct mutation taking a product input containing a name and selecting the name back.
Framework agnostic, with two separate integration packages
The library states that it is framework agnostic, but with Symfony and Laravel integrations available, and those are separate repositories, graphqlite-bundle and graphqlite-laravel. That distinction matters for how you adopt it. The core package is what defines the attributes and the schema derivation, and it does not need a web framework to run, so it is also usable in a plain PHP script or a custom runtime. The examples directory contains a single project, examples/no-framework, which is the reference for the framework-agnostic usage and the fastest way to see the library working without pulling in a framework. The topics list names attributes, graphql, laravel, php and symfony, so the intended audience is a PHP team with a framework, and the package is published on Packagist as thecodingmachine/graphqlite. The licence is MIT, the default branch is master, and the documentation lives at graphqlite.thecodingmachine.io.
Queries, mutations and subscriptions come from the same attribute vocabulary
The feature list describes the library as coming with batteries included, specifically queries, mutations, subscriptions, mapping of arrays and iterators, file uploads, extendable types and more. The inclusion of subscriptions alongside queries and mutations is the part that separates it from a basic schema generator, because a subscription is a long-lived connection rather than a request, and it needs the server to hold state per client. The mapping of arrays and iterators is the other capability that matters in practice, since a PHP codebase often returns a Doctrine collection or a generator rather than a plain array, and a naive schema generator would expose that as an unusable type. Extendable types cover the case where the same PHP class should appear in the schema with different fields in different places, which is common once a single entity is used for both a summary view and a detail view. File uploads are listed as included, and the mutation example shows a product being updated with an input object, so a file argument would follow the same attribute mechanism.
Contributions have to arrive with tests
The contribution rules are short and strict in a way worth noting. Contributions are welcomed via pull requests, and if you would like to discuss something before submitting a PR there is a discussions area, while a bug or issue should be submitted as an issue first. The merge condition is explicit: all PRs should have sufficient test coverage for any additions or changes, and PRs will not be merged without it. That is a healthier rule than the usual request for tests, because it names the condition rather than the hope. The repository carries the tooling that backs it up, with a phpunit.xml.dist for the test configuration, a phpstan.neon for static analysis, a phpcs.xml.dist and a .php_cs/ directory for coding style, and a website/ directory that holds the documentation sources. There is also a CHANGELOG and the usual .github/ directory for the workflow configuration, and the coverage badge in the readme points at a branch coverage graph.
Where GraphQLite is the wrong choice
Three situations argue against it. The first is a project that cannot use PHP 8 attributes, since attributes are the mechanism the entire library is built on and there is no annotation-based fallback described in the documentation, so a codebase on an older PHP has no path into this library. The second is a team that wants a schema-first design, where the contract is authored separately and the PHP classes implement it. That arrangement lets a frontend team own the API surface and lets you publish the schema before the implementation exists, and with GraphQLite the schema is a consequence of the PHP code, so the contract cannot be designed independently of the code. The third is a project where the GraphQL layer is a small part of a larger API strategy, because the library is a GraphQL server implementation with a schema derivation convention, and a team running REST, gRPC and GraphQL side by side will end up with three places where the API surface is described. The realistic alternative for the attribute-driven case is to keep the same idea and write the schema yourself with a schema-first library, which costs a second description of the API but gives you the ability to evolve the contract without touching the domain classes.
Editorial conclusion
Adopt GraphQLite when your PHP application already has the domain objects and you want the GraphQL schema to live in the same classes rather than in a separate schema file, and pick a schema-first library if your client team owns the contract. Verify first which PHP version your project runs, since attributes are the mechanism the library is built on, and check the framework integration package for Symfony or Laravel before writing framework code, because the core library is framework agnostic and the wiring lives elsewhere.
Frequently asked questions
What is GraphQLite?
It is a GraphQL library for PHP that allows you to use attributes, or annotations, to define your schema and write your queries and mutations using simple-to-write controllers. A complete GraphQL API can be created by simply annotating your PHP classes.
Does GraphQLite work without a framework?
Yes. The library is framework agnostic, with separate Symfony and Laravel integration packages available as graphqlite-bundle and graphqlite-laravel, and the repository includes an examples/no-framework project that shows the framework-agnostic usage.
What features does GraphQLite include?
Queries, mutations, subscriptions, mapping of arrays and iterators, file uploads and extendable types. The package is published on Packagist as thecodingmachine/graphqlite and is MIT licensed.
How are GraphQLite types and fields declared?
A class carries the Type attribute, optionally with Input to make it usable as a mutation argument, and each exposed property is a Field attribute on an ordinary method. The GraphQL type is derived from the PHP return type, and a controller method carries the Mutation attribute.
Is GraphQLite still maintained?
The repository is not archived and the last push was on 2026-10-19, with releases v8.3.1 from 2026-07-16, v8.3.0 from 2026-05-20 and v8.2.0 from 2026-04-22. The licence is MIT, the documentation is at graphqlite.thecodingmachine.io, and the project requires pull requests to come with sufficient test coverage.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/thecodingmachine-graphqlite)Was this useful?