Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Graphql Php Laravel Package

webonyx/graphql-php

A PHP implementation of the GraphQL specification, based on the JavaScript reference implementation. It's fully compliant with the October 2021 spec, with September 2025 compliance in progress, and supports schema building, query execution, and validation.

View on GitHub
Deep Wiki
Context7

Technical Evaluation

Architecture Fit

  • GraphQL Adoption: The package provides a full-featured GraphQL implementation for PHP, aligning with Laravel’s ecosystem (e.g., Lighthouse, GraphQL for Laravel). It supports October 2021 spec compliance with September 2025 in progress, making it suitable for modern GraphQL APIs.
  • Laravel Synergy: Integrates with Laravel’s dependency injection (DI), middleware, and routing systems. Can replace or extend existing GraphQL solutions (e.g., Lighthouse) while leveraging Laravel’s service container for resolvers, directives, and schema configuration.
  • Schema-First Design: Supports SDL (Schema Definition Language) and code-first approaches, fitting Laravel’s preference for declarative configurations (e.g., config/graphql.php).
  • Performance Optimizations: Recent versions (v15.x) include QueryPlan optimizations, reduced recursion, and native PHP type usage, improving execution speed and memory efficiency.
  • Document Normalization (v15.38.0): The Printer::stripIgnoredCharacters() removes characters that do not change a document’s meaning. Architecturally this is a canonicalization primitive — it enables stable document fingerprints for persisted queries / APQ, edge caching, and allow-listing without pulling in an external parser. It is a small, additive utility and does not alter existing schema or execution behavior.
  • Input Hardening (v15.38.0): Invalid UTF-8 in documents is now rejected at parse time. This closes an input-validation gap in the request pipeline, which is architecturally consistent with the package’s validation-rule layer and reduces exposure at the earliest possible stage (before execution planning).
  • Batch Error Semantics (v15.38.1): Malformed scalar entries in batched request payloads (e.g. ["x"] or {"query":"{ a }","0":"x"}) now raise a RequestError instead of a TypeError. This is an architectural correctness fix: TypeError is a PHP-level fault that escapes the GraphQL error envelope, whereas RequestError is a first-class client-error type that flows through the standard error formatter. It aligns batch handling with the rest of the request-error taxonomy — no schema or execution change.

Integration Feasibility

  • Middleware Integration: Can be wrapped in Laravel’s middleware pipeline (e.g., auth, rate-limiting) via StandardServer or custom middleware.
  • Resolver Flexibility: Supports class-based resolvers, callable resolvers, and dependency-injected resolvers (via Laravel’s container), reducing boilerplate.
  • Validation Rules: Extensible validation system (e.g., UniqueOperationTypes, QueryComplexity) aligns with Laravel’s validation ecosystem (e.g., Form Requests).
  • Error Handling: Customizable error formatting (e.g., FormattedError) integrates with Laravel’s exception handling (App\Exceptions\Handler).
  • Persisted Query Wiring: stripIgnoredCharacters() can be called once at the point where a query document is ingested (typically a thin controller or middleware) to produce a stable hash key before hitting Redis. No new runtime dependency, no configuration surface — integration cost is a few lines in existing request handling.
  • Batch Endpoint Wiring: If we expose batched requests (common with Apollo links), the v15.38.1 fix means malformed batch entries degrade to a standard RequestError response instead of a TypeError that would typically surface as a 500. No integration work required — it simply makes existing batch handling behave correctly.

Technical Risk

  • Migration Risk: If replacing Lighthouse or another GraphQL package, schema migration may require refactoring resolvers/directives to match graphql-php's API (e.g., FieldDefinition vs. Lighthouse’s Type).
  • Spec Compliance: September 2025 spec compliance is in progress, so edge cases (e.g., new directives) may need monitoring. Note this risk is unchanged by v15.38.0/1.
  • PHP Version: Requires PHP 7.4+, which may necessitate runtime upgrades for legacy Laravel apps (e.g., LTS 8.x).
  • Dependency Bloat: Large package (~100K LOC) may increase composer install time and memory usage during bootstrapping.
  • Upgrade Risk from v15.38.0 → v15.38.1: Low. Single patch fixing an error-type mismatch in batch handling. No signature changes, no deprecations, no schema changes. The only behavioral difference is that a class of malformed batch payloads now returns a RequestError (client error) instead of a TypeError (server fault).
  • HTTP Status Shift for Malformed Batches: Any monitoring or client logic that keyed off a 500 for these payloads will now see a 4xx/GraphQL error response. This is the correct behavior, but it will move error counts between buckets — worth a one-line note to anyone whose dashboards or alerts distinguish server faults from client faults.
  • Behavioral Surface of Normalization: stripIgnoredCharacters() changes whitespace/insignificant-character handling. If hashes generated by a different tool (or a prior ad-hoc preg_replace) are already stored, hashes will not match on cutover. Persisted-query allow-lists require a one-time regeneration or dual-lookup window.

Key Questions

  1. Schema Compatibility:

    • How will existing Lighthouse schemas (or other GraphQL packages) translate to graphql-php’s schema definition?
    • Are there automated migration tools or scripts to convert between formats?
  2. Performance Benchmarks:

    • How does graphql-php compare to Lighthouse or GraphQLite in query execution speed and memory usage for Laravel’s typical workloads (e.g., 100+ resolvers)?
  3. Tooling Ecosystem:

    • Does it support GraphQL Playground/Studio, persisted queries, or subscription protocols (e.g., WebSockets) out-of-the-box? (The persisted-query building block is now in-package via v15.38.0; the storage/transport layer remains ours to build.)
    • Are there Laravel-specific IDE tools (e.g., PHPStorm plugins) for schema introspection?
  4. Long-Term Maintenance:

    • What is the sustainability plan post-migration to the new repository (announced in the README)?
    • Are there backward-compatibility guarantees for Laravel-specific integrations?
  5. Security:

    • How does it handle query depth limiting, introspection security, and DoS protection (e.g., malicious queries) compared to Laravel’s built-in middleware?
    • Given the UTF-8 rejection fix, which upstream release line is our security floor — i.e., do we pin to >= 15.38.0 to guarantee this hardening rather than backporting it?
  6. Batch Support:

    • Do we actually expose batched GraphQL requests today (Apollo batching, custom clients)? If yes, v15.38.1 is more than cosmetic — it changes the observable status code for malformed batch entries. If no, the fix is absorbed silently.

Integration Approach

Stack Fit

  • Laravel Core Integration:
    • Replace or augment Lighthouse by binding the StandardServer to Laravel’s HTTP kernel (e.g., app/Http/Kernel.php).
    • Use Laravel’s service provider (GraphQLServiceProvider) to bootstrap the schema, resolvers, and middleware.
  • Dependency Injection:
    • Resolvers can leverage Laravel’s container (e.g., resolve(fn() => new UserResolver())).
    • Directives and validation rules can be registered via service provider.
  • Routing:
    • Map GraphQL endpoint to a route (e.g., Route::graphql()) using middleware for auth/validation.
    • Example:
      Route::post('/graphql', [GraphQLController::class, 'handle'])
          ->middleware(['auth:sanctum', 'throttle:60']);
      
  • Caching:
    • Leverage Laravel’s cache (e.g., Redis) for persisted queries or schema caching.
    • Use Printer::stripIgnoredCharacters() at document intake to produce the cache key, so cosmetic whitespace differences between clients collapse onto a single entry:
      $normalized = \GraphQL\Language\Printer::stripIgnoredCharacters($document);
      $key = 'gql:pq:' . hash('xxh128', $normalized);
      
  • Batch Handling:
    • No code change required. Ensure the controller does not catch \TypeError and re-wrap it into a 500 before the server’s error formatter sees it — that would negate the v15.38.1 benefit.

Migration Path

  1. Assessment Phase:
    • Audit existing GraphQL schema/resolvers for compatibility gaps (e.g., Lighthouse-specific syntax).
    • Benchmark performance against current setup (e.g., Lighthouse).
    • Inventory any place that already hashes or normalizes documents (custom APQ, CDN rules, allow-lists) — these define the migration blast radius for v15.38.0.
    • Confirm whether batch requests are in use; if so, review client-side error handling for the TypeError → RequestError shift.
  2. Parallel Run:
    • Deploy graphql-php alongside Lighthouse using different endpoints (e.g., /graphql, /graphql-old).
    • Use feature flags to gradually migrate clients.
  3. Schema Conversion:
    • Write a script to convert Lighthouse’s Type definitions to graphql-php’s Schema.
    • Example:
      $schema = Schema::create([
          'query' => new ObjectType([
              'name' => 'Query',
              'fields' => [
                  'user' => $userField, // Converted from Lighthouse
              ],
          ]),
      ]);
      
  4. Resolver Rewriting:
    • Replace Lighthouse’s @resolver directives with graphql-php’s class-based resolvers or callables.
    • Example:
      $schema->mutate([
          'directives' => [
              new DirectiveType([
                  'name' => 'auth',
                  'locations' => [DirectiveLocation::FIELD_DEFINITION],
                  'resolve' => fn($next) => $next(), // Custom logic
              ]),
          ],
      ]);
      
  5. Testing:
    • Validate introspection queries (__schema) match between old and new implementations.
    • Test edge cases (e.g., unions, interfaces, persisted queries, batched requests).
    • Add regression fixtures for non-UTF-8 request bodies to confirm the new rejection behavior surfaces as a clean GraphQL validation error, not a 500.
    • Add regression fixtures for malformed batch entries (["x"], {"query":"{ a }","0":"x"}) asserting a RequestError envelope and an appropriate 4xx status.

Compatibility

  • Laravel Ecosystem:
    • Works with Laravel Echo/Pusher for subscriptions (if using graphql-php's subscription support).
    • Integrates with Laravel Scout for GraphQL-based search queries.
  • Third-Party Packages:
    • GraphQL Playground/Studio: Compatible via standard GraphQL endpoint.
    • Apollo Client: Supports persisted queries and subscriptions; normalization is client-independent so long as both sides agree on the canonicalization function. Apollo’s batch link is the most likely consumer affected by v15.38.1’s error-type change.
  • Database Layer:
    • Resolvers can use Eloquent, Query Builder, or repositories as data sources.
  • Version Pin: Recommend pinning ^15.38 (rather than the previously implied ^15.12) so the UTF-8 hardening, normalization helper, and batch error fix are guaranteed present across all environments.

Sequencing

  1. Phase 1: Schema Migration
    • Convert SDL/code-first schema to graphql-php format.
    • Test introspection and basic queries.
  2. Phase 2: Resolver Porting
    • Rewrite resolvers to use graphql-php’s API.
    • Replace Lighthouse directives with custom directives or middleware.
  3. Phase 3: Performance Tuning
    • Optimize QueryPlan and caching.
    • Benchmark against Lighthouse.
  4. Phase 4: Normalization & Persisted Queries (optional, post-cutover)
    • Adopt stripIgnoredCharacters() for cache keys; regenerate existing persisted-query hashes during a dual-lookup window.
  5. Phase 5: Full Cutover
    • Deploy new endpoint, deprecate old one.
    • Monitor for errors (e.g., via Laravel’s Sentry or Log), watching for the new 4xx batch-error shape.

Operational Impact

Maintenance

  • Schema Updates:
    • Changes to the GraphQL schema can be versioned using Laravel’s migration system or schema diff tools.
    • Example workflow:
      # Generate a migration for schema changes
      php artisan graphql:schema-migrate
      
  • Resolver Updates:
    • Resolvers can be unit-tested using Laravel’s testing tools (e.g., tests/Feature/GraphQL/UserResolverTest.php).
    • Use dependency injection to mock services in tests.
  • Dependency Management:
    • Monitor graphql-php for breaking changes (e.g., via GitHub releases or composer update --dry-run).
    • Pin to a specific minor version (e.g., ^15.38) to avoid surprises and to hold the current security floor.
    • Cadence observation: v15.32.3 → v15.38.1 shipped across roughly six minor bumps plus two patches with only additive/fix-level entries. That is a low-churn, semver-respecting release stream — a positive signal for the maintenance story, and it means routine minor upgrades can be batched on a quarterly cadence rather than chased per release. The v15.38.0 → v15.38.1 turnaround (same-week patch) indicates the maintainers ship corrective fixes promptly.

Support

  • Debugging:
    • Use graphql-php's debug extensions (e.g., extensions.debug) to log query execution.
    • Integrate with Laravel’s debugbar for visualizing GraphQL queries.
  • Error Handling:
    • Customize FormattedError to include Laravel-specific context (e.g., user ID, request ID).
    • Example:
      $server->setErrorFormatter(function ($e, array $context) {
          return (new FormattedError($e))
              ->setExtensions([
                  'laravel' => [
                      'user_id' => auth()->id(),
                      'request_id' => request()->header('X-Request-Id'),
                  ],
              ]);
      });
      
    • New failure modes to instrument: UTF-8 rejection (v15.38.0) and malformed batch entries (v15.38.1) both arrive as client errors. Ensure dashboards separate these from execution errors, and that error payloads stay within the standard GraphQL envelope rather than tripping Laravel’s generic 500 handler. The v15.38.1 change is specifically about preventing a TypeError from escaping into the 500 path — confirm no controller-level catch-all re-introduces it.

Scaling

  • Execution Cost: Unchanged by these releases; scaling posture is still governed by QueryComplexity/depth limits and resolver-level N+1 control (e.g., batched loaders).
  • Edge Caching: stripIgnoredCharacters() materially improves hit rate for any CDN or Redis layer keyed on query text, since whitespace and comment differences no longer fragment the cache. Expect a measurable drop in cache-key cardinality if clients currently format queries inconsistently.
  • Throughput Effect of Input Hardening: Negligible; validation occurs pre-execution and is cheaper than executing a malformed document. Marginal positive effect on DoS resilience by rejecting some malformed payloads earlier. Batch-entry validation follows the same pattern — cheap, pre-execution.
  • Batch DoS Surface: Correctly classifying malformed batch entries as client errors also makes them easier to rate-limit and alert on, since they no longer masquerade as server faults.

Failure Modes

  • Persisted-Query Miss Storm: If hashes are regenerated without a dual-lookup window, unregistered clients fall back to full-document submission (or fail outright if APQ-only is enforced) — a classic cutover failure. Mitigate with a shadow period.
  • Encoding-Related Client Breakage: Non-UTF-8 or double-encoded request bodies that previously "worked" will now hard-fail. Most likely sources are legacy mobile clients, internal scripts, and replayed production traffic in staging. Worth a pre-upgrade log sweep.
  • Batch Error Reclassification: Malformed batch payloads that previously produced a TypeError/500 will now produce a RequestError/4xx. Risk is not correctness but observability and client behavior: alert rules keyed to 5xx will go quiet (good, but expect a monitoring gap), and any client that special-cased the old failure may behave oddly. Low likelihood, but worth a one-line comms note.
  • Cache Key Drift Between Services: If normalization is applied in the GraphQL service but not in an upstream gateway that also keys on the query, the two tiers will disagree. Normalization must be a single, shared, versioned function.
  • Silent Utility Misuse: stripIgnoredCharacters() operates on documents; applying it to non-document strings (e.g., raw JSON variables) is undefined usage. Guard at the call site.

Ramp-Up

  • Engineer Effort: Near zero for these releases — no API changes to learn. Effort concentrates in the optional persisted-query work (est. 1–2 days for a cache-key function, dual-lookup window, and hash regeneration job). The batch fix requires no engineering effort; at most a test fixture.
  • TPM Effort: Primarily version-pin hygiene (move ^15.12 → ^15.38) and a one-paragraph release note to client teams covering UTF-8 rejection and, if batched requests are in use, the batch error-type change. No architecture review, no stakeholder sign-off, no training required.
  • Recommendation: Adopt. Treat v15.38.0 and v15.38.1 as a routine, low-risk bump package that modestly improves caching, input validation, and error semantics. Ship the pair together in the next maintenance window, fold the persisted-query capability into the Phase 4 backlog, and only loop in client teams if batch requests are confirmed in the traffic mix.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
ably/pubsub-server
mstfkhazaal/defender
mfonte/base62x
karnoweb/metapilot
tobya/bcsapiwrapper
swalker2/cpanel
vish4395/laravel-translation-manager
morningtrain/economic
teksite/systeminfo-laravel
atomcms/voting
run6/weather
siokas/laravelembeddirectives
adamlien/pkuuids
gilsonsouza/lara-doc-generator
manelgavalda/enrollment_mobile
unabomber/timezone
delatbabel/contacts
astritzeqiri/g-recaptcha
kevinongko/laravel-genode
developeruz/laravel-analytics