thecodingmachine/graphqlite
GraphQLite is a framework-agnostic PHP library that lets you build a complete GraphQL API by annotating your classes. Define types, queries, mutations, and subscriptions with simple attributes and controller methods, with Symfony and Laravel integrations available.
Architecture fit
webonyx/graphql-php (the actual GraphQL execution engine), translating PHP attributes (#[Type], #[Field], #[Query], #[Mutation], #[Input], #[Security], #[Autowire]) into an executable schema at runtime..graphql SDL files) or hand-wiring webonyx types.thecodingmachine/graphqlite-laravel (a separate, smaller package) providing the service provider, config publishing, and route registration. This is a double-edged property: it means the core is not Laravel-idiomatic (expect PSR-11 container abstractions and a middleware pipeline that is GraphQLite's own, not Laravel's), and it means you are adopting two packages with independent release cadences.Integration feasibility
composer require thecodingmachine/graphqlite-laravel, publish config, define a types namespace/directory to scan, and the library reflects over those classes to build the schema. A working /graphql endpoint is achievable in a spike of a few days for a small domain.Validator rules for #[Input]-based user input validation, and #[Security]/#[Security("is_granted(...)")]-style field-level authorization alongside Laravel Gates/Policies.#[Input] types and getter/setter-backed input fields (v6.0.0), custom input validators (v6.0.0), void resolvers (v6.2.1), file uploads via the optional ecodev/graphql-upload package (demoted to "recommended" dependency in v4.1.0 — you must add it explicitly).Technical risk
#[Input] naming/default semantics changed; existing named input types without default silently change meaning), v6.1.0 (PSR-11 v2 required; interface signatures tightened — a hard break for anyone with custom type mappers), v4.0.2 (enum type naming BC break). A TPM must treat minor upgrades as potentially breaking and budget for it.webonyx/graphql-php major versions (v14.9 from GraphQLite 5.x, v15 from 6.2.0) and on PHP ^8.1 floor with testing on 8.2. Your PHP upgrade cadence is therefore coupled to this package's cadence, not just to Laravel's.webonyx directly. Release notes read as a small maintainer group with named individual contributors. There is real single-maintainer concentration risk, mitigated by MIT licensing and the fact that the output is a standard webonyx schema (so the escape hatch — hand-written type definitions — is viable, if laborious).types namespace takes down the entire endpoint.Key questions to resolve before commitment
php artisan config:cache and in a read-only container filesystem?webonyx/graphql-php majors, and what is our tolerance for a breaking #[Input]-style change landing in a patch/minor?webonyx?Stack fit
Migration path
/graphql, scope its scanned namespaces to a small new domain, and leave REST untouched. This gives a real schema with zero blast radius on existing controllers.#[Query]/#[Mutation] methods that delegate to existing application services/actions rather than reimplementing logic. The REST controller and the GraphQL resolver should be two thin adapters over the same service — this is the key discipline that keeps the migration reversible.rebing/graphql-laravel: not a mechanical translation. Lighthouse's directives/@field resolvers and rebing's config-driven type registry have no 1:1 mapping to attributes. Budget per-type manual work; reuse the business logic layer, rewrite the schema declaration layer.SchemaFactory::setDoctrineAnnotationReader in favor of native attributes. Combine this with the PHP 8.1 floor upgrade.Compatibility
thecodingmachine/graphqlite, thecodingmachine/graphqlite-laravel, and webonyx/graphql-php with caret constraints and a committed lockfile, and treat the two GraphQLite packages as a single upgrade unit — do not upgrade the core without upgrading the Laravel bridge in the same PR.ecodev/graphql-upload dependency plus the PSR-7 implementation (laminas/diactoros lineage). Do not assume uploads work out of the box.RootTypeMapperInterface implementations are a known breakage surface (v6.1.0 tightened signatures). Avoid extending the type mapper unless a requirement genuinely demands it.Sequencing
#[Security] vs. Gates), and a decision record on the N+1 strategy.Maintenance
webonyx/graphql-php majors will force coordinated work, and the BC-break history says "minor" is not a safety guarantee.Support
#[Type], #[Input], #[Field], #[Security], #[Autowire], validation assertions) as an internal standard. The library permits many ways to express the same field; unconstrained, the schema will drift stylistically and become hard to review.Scaling
#[Field] public function getAuthor(): User on a list of 100 posts is 100 queries. This is the single highest-impact operational risk and it will not show up in a spike with 3 records. Mitigate with eager-loading discipline, a batching layer, or field-level lazy resolution — and enforce it with query-count assertions in tests.Failure modes to design against
app/.composer update → schema or input-type semantics shift under existing clients. Mitigate with the SDL snapshot diff in CI and a lockfile discipline.Ramp-up
How can I help you explore Laravel packages today?