When directly querying Craft's GraphQL endpoint, attempting to query plugin-added schemas results in an error:
Schema must contain unique named types but contains multiple types named \"handle_BlockType\". Make sure that
resolveTypefunction of abstract type \"handle_FieldSchema\" returns the same type instance as referenced anywhere else within the schema (see http://webonyx.github.io/graphql-php/type-system/#type-registry).
This can be observed in Super Table and Neo. I'll also test ImageOptimize and Retour and update this issue.
You can get around this by doing either of two things:
1. Use any reference to __schema in the body of the query.
So...
{
entries(section: ["homepage"], limit: 1) {
... on homepage_homepage_Entry {
pageBlocks {
... on pageBlocks_serviceSummary_BlockType {
benefits {
... on benefits_BlockType {
text
}
}
}
}
}
}
}
...would fail while...
{
entries(section: ["homepage"], limit: 1) {
... on homepage_homepage_Entry {
pageBlocks {
... on pageBlocks_serviceSummary_BlockType {
benefits {
... on benefits_BlockType {
text
}
}
}
}
}
}
__schema {
types {
name
}
}
}
...would return the full schema as expected. Or,
2. Patch the GraphQL controller to skip the check for __schema:
diff --git a/src/controllers/GraphqlController.php b/src/controllers/GraphqlController.php
index b6b56db..5d7f0b6 100644
--- a/src/controllers/GraphqlController.php
+++ b/src/controllers/GraphqlController.php
@@ -140,7 +140,7 @@ class GraphqlController extends Controller
}
try {
- $schemaDef = $gqlService->getSchemaDef($schema, StringHelper::contains($query, '__schema'));
+ $schemaDef = $gqlService->getSchemaDef($schema, true);
$result = GraphQL::executeQuery($schemaDef, $query, null, null, $variables, $operationName)
->toArray(true);
} catch (\Throwable $e) {
The second method is the only way to avoid further errors working with Gatsby or Gridsome, where it's not always possible to jam __schema into its queries.
__schema { types { name } } in the query and try again.$schemaDef = $gqlService->getSchemaDef($schema, true);.I ended up doing the patch like Matt suggested, worked. I was trying to query Neo fields from Gatsby, and I had all the same errors he mentioned.
That patch will work, but it will also impact the performance of the site, especially as the site grows more complex.
We added a workaround/hack for Matrix (https://github.com/craftcms/cms/commit/f4b60b68694ab928974972c36fba5d147801b221), but that was one day before the conference, so it was really more of a "just get this in because we need something" fix. I'll see if I can add a better fix or maybe I have to just fork the GraphQL library we're using.
Fixed it better with https://github.com/craftcms/cms/commit/80192a55f8f89b129abff2b43d4a0c7d66d60f45, up to 3rd party plugins to follow suit.
(verbb/super-table#300)
Sorry to add noise to this issue @andris-sevcenko, but is there a reason this _doesn't_ work? My field returns a fixed array of scalar values so I don't think I need to get a resolver involved:
public function getContentGqlType()
{
$typeName = $this->handle.'_SnipcartField';
$productDetailsType = GqlEntityRegistry::getEntity($typeName)
?: GqlEntityRegistry::createEntity($typeName, new ObjectType([
'name' => $typeName,
'fields' => [
'sku' => Type::string(),
'price' => Type::float(),
'shippable' => Type::boolean(),
'taxable' => Type::boolean(),
'weight' => Type::float(),
'weightUnit' => Type::string(),
'length' => Type::float(),
'width' => Type::float(),
'height' => Type::float(),
'inventory' => Type::int(),
'dimensionsUnit' => Type::string(),
],
]));
return $productDetailsType;
}
The field _is_ defined and present in the schema; it autocompletes in GraphQL tools and everything. The type is registered with GqlEntityRegistry, and yet still I get this error when I try to perform the query:
Tried to load an unregistered type “productDetails_SnipcartField”. This can indicate both a typo in the query or an issue with the schema used.
If I add a__schema string to the query or patch the GraphQL controller, it works fine.
@mattstein because you also have to register the loader that will load this type:
TypeLoader::registerType($typeName, function () use ($productDetailsType) { return $productDetailsType ;});
Hoping to address this in a commit today by registering the loader behind the scenes when you're creating the type.
So close. Thanks @andris-sevcenko!
Most helpful comment
Fixed it better with https://github.com/craftcms/cms/commit/80192a55f8f89b129abff2b43d4a0c7d66d60f45, up to 3rd party plugins to follow suit.
(verbb/super-table#300)