Weave Code
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 Laravel Laravel Package

rebing/graphql-laravel

Code-first GraphQL integration for Laravel built on webonyx/graphql-php. Define schema in PHP (types, queries, mutations), support multiple schemas with per-schema middleware, resolver middleware, privacy rules, and data loading to avoid N+1 (dataloaders/SelectFields).

View on GitHub
Deep Wiki
Context7
## Getting Started

### Minimal Steps
1. **Installation**:
   ```bash
   composer require rebing/graphql-laravel
   php artisan vendor:publish --provider="Rebing\GraphQL\GraphQLServiceProvider"

Review config/graphql.php for schema configuration.

  1. Generate a Type:

    php artisan make:graphql:type UserType
    

    Define fields in app/GraphQL/Types/UserType.php:

    public function fields(): array {
        return [
            'id' => ['type' => Type::nonNull(Type::int())],
            'name' => ['type' => Type::nonNull(Type::string())],
        ];
    }
    
  2. Generate a Query:

    php artisan make:graphql:query UsersQuery
    

    Implement resolve() in app/GraphQL/Queries/UsersQuery.php:

    public function resolve($root, array $args): array {
        return User::all()->toArray();
    }
    
  3. Register Schema: Update config/graphql.php:

    'schemas' => [
        'default' => [
            'query' => [App\GraphQL\Queries\UsersQuery::class],
            'types' => [App\GraphQL\Types\UserType::class],
        ],
    ],
    
  4. Test:

    curl -X POST -H "Content-Type: application/json" \
      -d '{"query": "{ users { id name } }"}' \
      http://localhost:8000/graphql
    

First Use Case

Fetch Eloquent data with filtering:

// In UsersQuery.php
public function args(): array {
    return [
        'name' => ['type' => Type::string()],
    ];
}

public function resolve($root, array $args): array {
    return User::when($args['name'], fn($q) => $q->where('name', 'like', "%{$args['name']}%"))
               ->get()
               ->toArray();
}

Query:

query {
  users(name: "John") {
    id
    name
  }
}

Implementation Patterns

Core Workflows

  1. Type-Driven Development:

    • Define types first (UserType, PostType), then queries/mutations that use them.
    • Example: Create PostType with author field (type: UserType), then use it in PostsQuery.
  2. Resolver Patterns:

    • Simple Resolver: Directly return data (e.g., return User::find($id)).
    • Deferred Resolver (Dataloaders):
      public function resolve($root, array $args) {
          return $this->load('users')->loadMany($args['ids']);
      }
      
      Register loader in bootstrap.php:
      GraphQL::addDataloader('users', fn() => new UserLoader());
      
  3. Schema Organization:

    • Multi-schema: Useful for microservices or feature flags.
      'schemas' => [
          'admin' => ['query' => [AdminQuery::class]],
          'public' => ['query' => [PublicQuery::class]],
      ],
      
    • Route schemas via attributes:
      #[GraphQLSchema('admin')]
      class AdminQuery extends Query { ... }
      
  4. Validation Integration:

    • Inline Rules:
      public function args(): array {
          return [
              'email' => [
                  'type' => Type::nonNull(Type::string()),
                  'rules' => ['required', 'email'],
              ],
          ];
      }
      
    • Custom Validation:
      public function rules(): array {
          return ['email' => ['required', 'email', Rule::unique('users')]];
      }
      

Integration Tips

  1. Eloquent Integration:

    • Use rebing/graphql-laravel-select-fields for optimized queries:
      use Rebing\GraphQL\Laravel\SelectFields\SelectFields;
      SelectFields::macro('user', fn($query) => $query->select(['id', 'name']));
      
    • In UserType:
      public function fields(): array {
          return [
              'posts' => [
                  'type' => Type::listOf(GraphQL::type('Post')),
                  'resolve' => fn($user) => $user->posts,
                  'selectFields' => ['title', 'published_at'],
              ],
          ];
      }
      
  2. Middleware Stack:

    • HTTP Middleware: Restrict schemas by role:
      GraphQL::addHttpMiddleware('admin', fn($request, $next) => auth()->check() ? $next($request) : abort(403));
      
    • Execution Middleware: Add auth context:
      GraphQL::addExecutionMiddleware('auth', new class implements ExecutionMiddleware {
          public function handle($schemaName, $schema, $params, $root, $context, Closure $next) {
              $context['user'] = auth()->user();
              return $next($schemaName, $schema, $params, $root, $context);
          }
      });
      
  3. Testing:

    • Use TestCase helpers:
      public function test_users_query() {
          $response = $this->httpGraphql('{ users { id name } }');
          $response->assertJson(['data' => ['users' => [...]]);
      }
      
    • Mock resolvers:
      GraphQL::addResolverMiddleware('mock', fn($root, $args, $context, $info, $next) => [
          'id' => 1,
          'name' => 'Mock User',
      ]);
      
  4. Performance:

    • Batching: Use DataLoader for N+1 queries:
      GraphQL::addDataloader('users', fn() => new DataLoader(fn($ids) => User::whereIn('id', $ids)->get()));
      
    • Pagination: Leverage RelayConnection or custom cursors:
      use Rebing\GraphQL\Support\Facades\GraphQL;
      GraphQL::addType('Connection', RelayConnection::class);
      

Gotchas and Tips

Pitfalls

  1. Introspection:

    • Disabled by default in production. Enable via .env:
      GRAPHQL_DISABLE_INTROSPECTION=false
      
    • Gotcha: Forgetting to enable breaks GraphiQL and IDE tooling.
  2. Circular Dependencies:

    • Types referencing each other (e.g., UserPostUser) cause infinite loops.
    • Fix: Use resolveType() for interfaces/unions or lazy-load fields.
  3. Non-Null Fields:

    • Marking fields as nonNull without ensuring data availability causes runtime errors.
    • Tip: Use Type::nonNull(Type::string()) sparingly; prefer nullable fields with default values.
  4. Dataloader Caching:

    • Loaders cache by default. Clear cache manually if data changes:
      GraphQL::getDataloader('users')->clear();
      
  5. Validation Timing:

    • Validation runs before resolver middleware. Override authorize() for post-validation checks.

Debugging

  1. Error Formatting:

    • Customize error responses in config/graphql.php:
      'error_formatter' => Rebing\GraphQL\Support\ErrorFormatter::class,
      
    • Tip: Extend ErrorFormatter to hide sensitive data:
      public function formatError(Error $error, array $context) {
          return parent::formatError($error, [
              'message' => $error->getMessage(),
              'extensions' => ['code' => $error->getCode()],
          ]);
      }
      
  2. Query Complexity:

    • Enable analysis in config/graphql.php:
      'query_complexity' => [
          'enabled' => env('GRAPHQL_QUERY_COMPLEXITY', false),
          'max_complexity' => 1000,
      ],
      
    • Gotcha: Complex queries hit limits silently. Monitor with:
      GraphQL::addExecutionMiddleware('complexity', new QueryComplexityMiddleware());
      
  3. Middleware Order:

    • Execution middleware runs before resolver middleware. Debug with:
      GraphQL::addExecutionMiddleware('log', new class implements ExecutionMiddleware {
          public function handle($schemaName, $schema, $params, $root, $context, Closure $next) {
              \Log::info('Execution middleware', ['params' => $params]);
              return $next($schemaName, $schema, $params, $root, $context);
          }
      });
      

Tips

  1. Type Modifiers:
    • Use GraphQL::type() with modifiers:
      'users
      
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.
codraw/framework-extra-bundle
codraw/messenger
codraw/security
codraw/mailer
codraw/contracts
codraw/profiling
codraw/dependency-injection
codraw/tester
codraw/core
nexmo/api-specification
capell-app/block-library
axium/identity
cetria/laravel-dummy-models
cetria/reflection-helper
agropredict/sso-auth-bundle
evolvestudio/spam-protection
datacore/hub-sdk
develia/commons
cuci/prototurk-sdk
cuci/prototurk-sdk-symfony