medlabmg/youshido-graphql-extended
Extended fork of the Youshido GraphQL package for PHP, layering additional types, helpers, and fixes onto the original library. Suited to PHP and Laravel projects building GraphQL schemas, though the exact additions should be confirmed in the repo.
Install and register. This is a Symfony bundle that layers convenience on top of youshido/graphql-bundle, so the install is the usual two-step:
composer require medlabmg/youshido-graphql-extended
Then register it in app/AppKernel.php (Symfony ≤4) or config/bundles.php (Symfony 4+), after the base Youshido\GraphQLBundle\YoushidoGraphQLBundle entry so its compiler passes run against the base services.
Where to look first. The README on the repo is the only doc you get, and with zero stars/dependents there is no community knowledge to lean on. Budget the first hour for reading source instead of docs:
src/DependencyInjection/*Extension.php and *CompilerPass.php — this tells you exactly which service tags and config keys the bundle adds (that is effectively its API).src/Resources/config/services.yml — the services it registers and what it decorates/overrides from the base bundle.YoushidoGraphQLBundle schema-building code, since everything here is a thin layer over it.First use case. Take a trivial Query.hello: String type, expose it through whatever schema class the extension expects (base-bundle SchemaInterface implementation or a tagged type service — check the compiler pass), and curl the GraphQL endpoint (/graphql by default in the base bundle). Confirm introspection works ({ __schema { queryType { name } } }) before building anything else; if introspection is broken, the extension's service wiring is misconfigured, not your type.
Types as services, not as a monolithic schema class. The reason to use this bundle over raw youshido/graphql is that it turns type registration into Symfony service wiring. The day-to-day pattern is:
Query/Mutation types as thin aggregators that compose the tagged types.This makes types autowirable — inject repositories, a security checker, a logger into a type class directly, which is the main ergonomic win over the base library's more manual approach.
Resolvers should stay dumb. Put query logic in services/repositories and let type classes do argument validation and shape the response. With a Symfony DI container behind you, the temptation to put Doctrine queries inside resolve() is strong; resist it. It keeps types testable without booting the kernel and keeps N+1 problems visible in one layer.
Mutations as paired input/result types. Define an input type for arguments and a dedicated payload type per mutation (errors array + mutated entity). This is the standard Relay-ish pattern and scales far better than returning bare scalars — clients can distinguish "null because not found" from "null because forbidden."
Extend via decoration, not by editing vendor. If the extension's default behavior doesn't fit (error formatting, field naming, default pagination), decorate the relevant service in your app's services.yml rather than forking. Because the bundle is obscure and unmaintained, decoration is also your migration path: when you eventually drop it, your overrides are already in your codebase, not in vendor/.
Testing. Write functional tests that POST a query string to the endpoint through KernelBrowser/WebTestCase and assert on JSON. Unit-test type classes by instantiating them with mocked collaborators. Snapshot the introspection result once — it's a cheap regression test that catches accidental type renames and broken tag registration after a cache clear.
Abandonware risk is the headline. Zero stars, zero dependents, vague one-line description. Treat this as a vendored internal package: pin an exact version in composer.json, commit composer.lock, and be prepared to fork. Audit the source before it touches production — you are the only reviewer this code will ever get.
Base-library age is the real constraint. youshido/graphql saw its last meaningful releases years ago and targets PHP 7.x. On PHP 8 you will likely hit Curry/reflection deprecations, dynamic property warnings, or return-type incompatibilities. Verify the whole dependency chain compiles under your PHP version before designing around it. If it doesn't, this package is not viable regardless of what it adds.
Symfony version coupling. The bundle registration mechanism (AppKernel vs bundles.php) and the DI config format (YAML service definitions vs autoconfigure/autowire) both changed across Symfony 3/4/5. Confirm the extension's DependencyInjection code parses your config format; a bundle that only ships a YAML services.yml will not autowire your tagged types without extra config.
Cache invalidation on type changes. Compiler-pass-collected tags are cached. After adding or retagging a type, bin/console cache:clear — otherwise you'll debug a "type not found" error that doesn't exist in the source.
Debug schema problems by dumping it, not by reading errors. GraphQL error messages are deliberately vague in production. Build the schema in a console command or test and var_dump/json_encode it, or run an introspection query in dev. Most "field is null" bugs are a missing service tag, not a resolver bug.
Error masking. The base library respects debug for exception details; make sure the extension doesn't override that default. Leaking stack traces through GraphQL responses in production is a common misconfiguration when bundles ship their own error formatter.
N+1 is invisible until it isn't. GraphQL's per-field resolution invites N+1 queries on nested types. There is no DataLoader in this older stack — batch in your resolver layer (eager-load associations, or pre-fetch by ID list) before you ship nested lists.
Extension points to prefer. Service tags (for new types/fields), service decoration (for behavior changes), and config keys exposed by the bundle's DI extension. Avoid subclassing the bundle's own classes — with no upstream maintenance, your subclasses become the fork without the benefits of an explicit fork.
How can I help you explore Laravel packages today?