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 Bundle Laravel Package

bastsys/graphql-bundle

View on GitHub
Deep Wiki
Context7
## Getting Started

### Minimal Setup
1. **Installation**:
   ```bash
   composer require bastsys/graphql-bundle

Add the bundle to config/bundles.php:

return [
    // ...
    Bastsys\GraphQLBundle\BastsysGraphQLBundle::class => ['all' => true],
];
  1. First Endpoint: The bundle auto-registers /graphql endpoint. Test it immediately with a query like:

    query {
        __schema {
            types {
                name
            }
        }
    }
    

    (Send via Postman/cURL with Content-Type: application/json.)

  2. Define a Basic Type: Create a resolver class (e.g., src/GraphQL/Resolver/Query.php):

    namespace App\GraphQL\Resolver;
    
    use Bastsys\GraphQLBundle\Resolver\AbstractResolver;
    use Bastsys\GraphQLBundle\Type\Type;
    
    class Query extends AbstractResolver
    {
        public function hello(): string
        {
            return 'Hello, GraphQL!';
        }
    }
    

    Register it in config/packages/bastsys_graphql.yaml:

    bastsys_graphql:
        resolvers:
            query: App\GraphQL\Resolver\Query
    
  3. Query the Resolver:

    query {
        hello
    }
    

Implementation Patterns

1. Resolver Architecture

  • Query/Mutation Structure: Organize resolvers by operation type (e.g., Query, Mutation, Subscription). Example:

    // src/GraphQL/Resolver/Mutation.php
    class Mutation extends AbstractResolver
    {
        public function createUser(string $name): array
        {
            // Logic here
            return ['name' => $name, 'id' => 1];
        }
    }
    

    Register in bastsys_graphql.yaml:

    bastsys_graphql:
        resolvers:
            mutation: App\GraphQL\Resolver\Mutation
    
  • Nested Resolvers: Use AbstractContainerAwareField for dependency injection:

    use Bastsys\GraphQLBundle\Field\AbstractContainerAwareField;
    
    class UserField extends AbstractContainerAwareField
    {
        public function resolve($root, array $args)
        {
            return $this->container->get('user.repository')->find($args['id']);
        }
    }
    

    Register the field in your resolver’s buildSchema() method.


2. Type System

  • Custom Types: Define types via PHP classes (e.g., src/GraphQL/Type/UserType.php):

    use Bastsys\GraphQLBundle\Type\ObjectType;
    
    class UserType extends ObjectType
    {
        public function __construct()
        {
            $this->addField('id', 'ID');
            $this->addField('name', 'String');
        }
    }
    

    Use in resolvers:

    public function getUser(): UserType
    {
        return new UserType(['id' => 1, 'name' => 'John']);
    }
    
  • Input Types: For mutations, create input types (e.g., UserInputType):

    use Bastsys\GraphQLBundle\Type\InputType;
    
    class UserInputType extends InputType
    {
        public function __construct()
        {
            $this->addField('name', 'String');
        }
    }
    

    Use in mutations:

    public function createUser(UserInputType $input): UserType
    {
        // ...
    }
    

3. Service Integration

  • Inject Services: Use AbstractContainerAwareField or Symfony’s DI:

    class Query extends AbstractResolver
    {
        private $userService;
    
        public function __construct(UserService $userService)
        {
            $this->userService = $userService;
        }
    
        public function getUsers(): array
        {
            return $this->userService->all();
        }
    }
    
  • Service Methods as Callables: Register service methods directly in bastsys_graphql.yaml:

    bastsys_graphql:
        resolvers:
            query:
                getUsers: ['@user.service', 'all']
    

4. Security

  • Authentication: Use Symfony’s security component in resolvers:

    public function protectedData(): string
    {
        if (!$this->container->get('security.token_storage')->getToken()) {
            throw new \Exception('Unauthorized');
        }
        return 'Secret data';
    }
    

    Or via middleware (extend GraphQLMiddleware).

  • Authorization: Implement custom logic in resolvers:

    public function deleteUser(int $id): bool
    {
        $user = $this->container->get('user.repository')->find($id);
        if (!$this->container->get('security.authorization_checker')->isGranted('ROLE_ADMIN')) {
            throw new \Exception('Forbidden');
        }
        return $user->delete();
    }
    

5. Schema Composition

  • Dynamic Schema: Build schemas programmatically in resolvers:

    public function buildSchema()
    {
        $schema = $this->schemaFactory->createSchema();
        $schema->addType(new UserType());
        $schema->addQuery($this->createQueryType());
        return $schema;
    }
    
  • Fragments and Interfaces: Use PHP interfaces for shared fields:

    interface NodeInterface {
        public function getId();
    }
    
    class UserType extends ObjectType implements NodeInterface { ... }
    

Gotchas and Tips

1. Common Pitfalls

  • Circular Dependencies: Avoid circular references in resolvers/types. Use lazy-loading or interfaces to break cycles.

  • Type Mismatches: Ensure resolver return types match GraphQL type definitions. Example:

    // ❌ Fails: Returns `array` but expects `UserType`
    public function getUser(): array { ... }
    
    // ✅ Works
    public function getUser(): UserType { return new UserType(...); }
    
  • Case Sensitivity: GraphQL field names are case-sensitive. Match resolver method names exactly (e.g., getUser vs getuser).


2. Debugging

  • Schema Validation: Use the /graphql endpoint with introspection to validate your schema:

    query {
        __schema {
            types {
                name
                fields {
                    name
                    type {
                        name
                    }
                }
            }
        }
    }
    
  • Error Handling: Catch exceptions in resolvers and return GraphQL errors:

    public function riskyOperation(): string
    {
        try {
            // ...
        } catch (\Exception $e) {
            throw new \Bastsys\GraphQLBundle\Exception\GraphQLException(
                $e->getMessage(),
                ['code' => $e->getCode()]
            );
        }
    }
    
  • Logging: Enable debug mode in bastsys_graphql.yaml:

    bastsys_graphql:
        debug: true
    

    Logs appear in Symfony’s profiler or var/log/dev.log.


3. Configuration Quirks

  • Resolver Priority: Resolvers are loaded in alphabetical order. Use explicit keys in bastsys_graphql.yaml to control order:

    bastsys_graphql:
        resolvers:
            query:
                getUsers: App\GraphQL\Resolver\Query::getUsers
                listUsers: App\GraphQL\Resolver\Query::listUsers
    
  • Caching: Disable caching during development (debug: true). Enable in production:

    bastsys_graphql:
        cache:
            enabled: true
            adapter: apcu
    
  • Introspection: Disable introspection in production for security:

    bastsys_graphql:
        introspection:
            enabled: false
    

4. Extension Points

  • Custom Directives: Extend the bundle’s directive system:

    use Bastsys\GraphQLBundle\Directive\AbstractDirective;
    
    class DeprecatedDirective extends AbstractDirective
    {
        public function validate($value, array $args, $context)
        {
            if (isset($args['reason'])) {
                return true;
            }
            throw new \Exception('Deprecated without reason');
        }
    }
    

    Register in bastsys_graphql.yaml:

    bastsys_graphql:
        directives:
            deprecated: App\GraphQL\Directive\DeprecatedDirective
    
  • Middleware: Add custom middleware (e.g., for logging or auth):

    use Bastsys\GraphQLBundle\Middleware\GraphQLMiddlewareInterface;
    
    class LoggingMiddleware implements GraphQLMiddlewareInterface
    {
        public function handle($request, \Closure $next)
        {
            $start = microtime(true);
            $response = $next($request
    
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.
terminal42/code-quality-tools
codifyo/ts-generator-bundle
andydefer/laravel-cluster
testo/fiber
mintobit/jobqueue
a4sex/maintenance-bundle
a4sex/entity-date-update
a4sex/client-identifier
a4sex/base-utilites
a4sex/key-value-storage
a4sex/micro-status
chilldev/dependency-injection-extra
datinglibre/datinglibre-app-api
biberltd/corebundle
bricre/symfony-bundle-test
biberltd/logbundle
dominium/http-adapter-bundle
dominium/google-analytics
a4sex/auto-clean-entity
christhompsontldr/laravel-inky