Installation Add the bundle via Composer:
composer require bnnvara/graphql-bundle
Enable the bundle in config/bundles.php:
return [
// ...
Bnnvara\GraphQLBundle\BnnvaraGraphQLBundle::class => ['all' => true],
];
Basic Configuration
Define a minimal config/packages/bnnvara_graphql.yaml:
bnnvara_graphql:
schema:
query: 'App\\GraphQL\\Query\\Query'
mutation: 'App\\GraphQL\\Mutation\\Mutation'
debug: '%kernel.debug%'
First Query
Create a simple resolver (e.g., src/GraphQL/Query/Query.php):
namespace App\GraphQL\Query;
use GraphQL\Type\Definition\Type;
use GraphQL\Type\Definition\ResolveInfo;
class Query
{
public function hello()
{
return 'World';
}
}
Define a schema in config/graphql/schema.graphqls:
type Query {
hello: String
}
Test via HTTP:
curl -X POST http://your-app/_graphql \
-H "Content-Type: application/json" \
-d '{"query": "{ hello }"}'
Dependency Injection Use Symfony’s DI to inject services into resolvers:
use Symfony\Component\HttpKernel\KernelInterface;
class Query
{
public function __construct(private KernelInterface $kernel) {}
public function env()
{
return $this->kernel->getEnvironment();
}
}
Input Types
Define input types in src/GraphQL/Type/Input/InputType.php:
namespace App\GraphQL\Type\Input;
use GraphQL\Type\Definition\Type;
class CreateUserInput
{
public function build(): Type
{
return Type::nonNull(Type::string());
}
}
Mutations
Implement mutations in src/GraphQL/Mutation/Mutation.php:
class Mutation
{
public function createUser(string $name)
{
// Logic here
return ['name' => $name];
}
}
Schema Stitching
Extend the schema dynamically via BnnvaraGraphQLBundle::extendSchema() in a compiler pass:
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\DependencyInjection\ContainerBuilder;
class GraphQLSchemaPass implements CompilerPassInterface
{
public function process(ContainerBuilder $container)
{
$definition = $container->findDefinition('bnnvara_graphql.schema');
$definition->addMethodCall('extendSchema', [/* custom schema */]);
}
}
Symfony Forms
Use Symfony\Component\Form\FormFactoryInterface in resolvers to validate input:
use Symfony\Component\Form\FormFactoryInterface;
class Mutation
{
public function __construct(private FormFactoryInterface $formFactory) {}
public function createUser(array $input)
{
$form = $this->formFactory->createNamedBuilder('user', UserType::class, $input);
if ($form->isSubmitted() && $form->isValid()) {
return $form->getData();
}
throw new \RuntimeException('Invalid input');
}
}
Doctrine ORM
Inject Doctrine\ORM\EntityManagerInterface for database operations:
use Doctrine\ORM\EntityManagerInterface;
class Query
{
public function __construct(private EntityManagerInterface $em) {}
public function users()
{
return $this->em->getRepository(User::class)->findAll();
}
}
Authentication Use Symfony’s security component to restrict resolvers:
use Symfony\Component\Security\Core\Security;
class Query
{
public function __construct(private Security $security) {}
public function secret()
{
if (!$this->security->isGranted('ROLE_ADMIN')) {
throw new \RuntimeException('Unauthorized');
}
return 'Secret data';
}
}
Caching
Enable schema caching in config/packages/bnnvara_graphql.yaml:
bnnvara_graphql:
schema:
cache: true
Schema Validation
.graphqls and PHP resolvers cause runtime errors.php bin/console bnnvara:graphql:validate to check schema consistency.Circular Dependencies
Query injecting Mutation and vice versa) fail silently.Debugging
debug: true) logs are verbose and may clutter production.BNNVARA_GRAPHQL_DEBUG env var to toggle dynamically:
debug: '%env(bool:BNNVARA_GRAPHQL_DEBUG)%'
Performance
Doctrine\ORM\QueryBuilder with join() or DQL for batch loading.GraphQL Playground Enable the built-in playground for interactive testing:
bnnvara_graphql:
playground: true
Access at /_graphql-playground.
Logging Configure Monolog to log GraphQL errors:
monolog:
handlers:
graphql:
type: stream
path: "%kernel.logs_dir%/graphql.log"
level: error
channels: ["graphql"]
Error Handling
Customize error formatting in config/packages/bnnvara_graphql.yaml:
bnnvara_graphql:
error_formatter: App\GraphQL\ErrorFormatter
Implement App\GraphQL\ErrorFormatter to extend GraphQL\Error\Formatter\ErrorFormatterInterface.
Custom Directives Register directives via a compiler pass:
$definition->addMethodCall('addDirective', [
'deprecated',
new Reference('App\GraphQL\Directive\DeprecatedDirective')
]);
Middleware Add middleware to the GraphQL pipeline:
bnnvara_graphql:
middleware:
- App\GraphQL\Middleware\AuthMiddleware
- App\GraphQL\Middleware\LoggingMiddleware
Validation Rules Extend input validation with custom rules:
use GraphQL\Validator\Rules;
class CustomRules extends Rules
{
public function validateCustomRule()
{
// Custom logic
}
}
Register in config/packages/bnnvara_graphql.yaml:
bnnvara_graphql:
validator:
rules: ['@App\GraphQL\Validator\CustomRules']
Subscription Support Enable subscriptions via Mercure or custom logic:
bnnvara_graphql:
subscriptions:
enabled: true
hub_url: '%env(MERCURE_HUB_URL)%'
How can I help you explore Laravel packages today?