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

garlic/graphql

garlic/graphql is a Laravel package for building GraphQL APIs in PHP. It helps define schemas and types, wire resolvers, and execute queries against your application, giving teams a structured way to expose Eloquent-backed data and custom logic through a single GraphQL endpoint.

View on GitHub
Deep Wiki
Context7

Getting Started

Reality check first. This bundle has 3 stars, 0 dependents, and its last release was 2019-12-23. Treat it as an internal-convention library rather than a maintained community package: there is no StackOverflow footprint, no blog posts, and issue responses are unlikely. Before you build on it, spend ten minutes confirming it installs against your PHP/Symfony versions — that single check decides whether the rest of this assessment applies to you.

Minimal path:

composer require garlic/graphql

Then register the bundle the way you would any Symfony bundle:

// config/bundles.php
return [
    // ...
    Garlic\GraphQLBundle\GarlicGraphQLBundle::class => ['all' => true],
];

Verify the class name against vendor/garlic/graphql-bundle/src/ — do not assume it matches the pattern above. If the bundle does not appear in config/bundles.php after install (older bundles relied on Flex recipes that no longer exist), register it manually.

Where to look first, in this order:

  1. vendor/garlic/graphql-bundle/composer.json — PHP constraint, Symfony constraint, and the actual GraphQL library it wraps (most likely webonyx/graphql-php or overblog/graphql-bundle). This tells you which upstream docs actually apply.
  2. vendor/garlic/graphql-bundle/DependencyInjection/Configuration.php — the full config tree. This is your real documentation.
  3. vendor/garlic/graphql-bundle/Resources/config/ — the service definitions, which reveal the tags and interfaces you need to implement.
  4. README.md — read it last, because it is almost certainly thinner than the code.

First use case. The bundle's stated purpose is inter-service communication in a Garlic microservice fleet. The smallest useful thing to build is: one service exposes a single query field over the bundle's endpoint, and a second service consumes it. Wire that end-to-end before designing any schema. If the producer/consumer round trip does not work, no amount of schema design will save the integration.

# config/packages/garlic_graphql.yaml
garlic_graphql:
    # copy keys verbatim from Configuration.php; do not guess
    endpoint: /graphql

Implementation Patterns

Schema as the service contract. In a microservice fleet the schema is the API. Keep each service's schema in a dedicated file (config/graphql/schema.graphql) rather than building it in PHP, so it can be diffed in code review and shared with consuming teams. Version it alongside the service, and treat field removal as a breaking change.

Resolvers as services. The idiomatic Symfony shape — and almost certainly what the bundle expects — is tagged services implementing a resolver interface:

final class OrderResolver implements ResolverInterface
{
    public function __construct(private OrderRepository $orders) {}

    public function resolve($root, array $args, $context, ResolveInfo $info): array
    {
        return $this->orders->findByCustomer($args['customerId']);
    }
}

Check Resources/config/ for the exact tag name (garlic_graphql.resolver or similar) and whether the mapping is by tag attribute or by convention. Inject repositories and clients via the constructor — never pull from the container inside a resolver, or you lose testability, which is the main thing this pattern buys you.

Cross-service calls belong behind a client, not in resolvers. The point of the bundle is service-to-service GraphQL. Wrap each downstream service in a small typed client class and inject that into the resolver. A resolver that opens an HTTP connection is a resolver you cannot unit test.

Propagate identity explicitly. In a fleet, the incoming request's user is not automatically the downstream request's user. Forward the auth token (or an internal service token plus the acting user ID) as a header on every downstream call. Make this a single helper so nobody forgets it in one resolver out of twenty.

Batch and cache per-request. Nested queries will produce N+1 downstream calls. Use a per-request batcher (a DataLoader-style deferred map keyed by entity ID) and a per-request memo cache for identical downstream queries. Both should be scoped to the request, not the process — long-lived caches across requests leak data between users in a PHP-FPM worker.

Explicit error mapping. Convert downstream HTTP failures, timeouts, and GraphQL errors arrays into a small set of domain exceptions, then map those to GraphQL errors in one place. Do not let raw transport exceptions bubble into the errors payload — they leak internal hostnames and stack traces to clients.

Test at the schema boundary. Integration tests that POST a query string to the endpoint and assert on the JSON response catch more real bugs than unit-testing resolvers, especially in a package this thin. Keep a fixture set of canonical queries that every service in the fleet runs against its consumers in CI.

Gotchas and Tips

Dependency constraints are the first blocker. A 2019 bundle targets PHP 7.x and Symfony 3/4. On PHP 8.1+ or Symfony 6 you will likely hit deprecations, removed interfaces, or a hard composer conflict. Options, in order of preference: (a) if the constraint is only in composer.json, fork and widen it, verifying the code actually runs; (b) replace the bundle with plain webonyx/graphql-php plus a thin Symfony controller — the bundle's value over the underlying library is small; (c) pin your service to an older runtime, which is a cost you will pay for years.

There is no community to debug against. When something breaks, grep -rn in vendor/garlic/graphql-bundle/ is your primary tool. Read DependencyInjection/Configuration.php and the compiler passes before touching config — most "it's not working" reports in bundles of this vintage are a config key silently ignored because it lives under a different node than you assumed.

Config keys fail open. Old bundles often treat unknown keys as harmless. Add ->validate() awareness: run bin/console config:dump-reference garlic_graphql and diff the output against your YAML. Anything you wrote that is not in the dump is doing nothing.

Commit the lock file and vendor the fork. With zero dependents and a stale release, an unattended composer update is a real risk. If you patch anything, fork it, tag it, and point repositories at your fork — do not leave an inline patch that the next developer will silently lose.

Disable introspection in production. It is a schema-disclosure endpoint. Gate it behind an env flag and require auth on the endpoint itself; the bundle predates most of the current GraphQL security defaults and will not do this for you.

Watch the query depth and complexity. No depth limit means a single nested query can fan out into hundreds of downstream calls across the fleet. Add a depth/complexity validator at the endpoint — this is the highest-value hardening you can do on a microservice GraphQL gateway.

Timeouts and circuit breaking. Every downstream resolver needs a connect timeout and a total timeout, and ideally a circuit breaker. A slow service in a fleet without timeouts becomes a fleet-wide outage via thread exhaustion. Set them at the client layer, not per-resolver.

Extension points are the bundle's interfaces. If you need logging, metrics, or auth, implement the bundle's own middleware/directive hooks rather than subclassing internal classes. Subclassing ties you to private implementation details in a package nobody is patching.

Debugging checklist. Blank/500 on the endpoint: check the bundle is registered and the route is loaded (bin/console debug:router | grep -i graphql). Empty data with errors: dump $exception->getPrevious() — wrapped transport errors hide the real cause one level down. Resolver never invoked: check the service is tagged and public/autowired correctly with bin/console debug:container --tag=<tag>.

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.
3mdikram/worldmoneywords
snowsoft/config
itmosoft/laravel-subscriptions
larva/laravel-ai-qwen
diephp/sequences
users-au/socialite-provider
twidpay/twid-logger
mrnewport/laravel-plaid
mrnewport/laravel-repo
mrnewport/laravel-docsign
mrnewport/laravel-stow
mrnewport/laravel-flow
mrnewport/laravel-priceable
mrnewport/laravel-nestedterms
fredmeng/laravel-apidoc-generator
itstructure/laravel-multilingual-tools
pdustdar/elasticsearch
markupai/php-sdk
rlacerda83/lumem-microservice-shipment
uni-method/symfony-lib