how are you doing?
I'm struggling with unions I'd like some clarification in regards of custom resolvers for union type based on custom types. Mi current schema is this for product.graphql
which is imported inside schema.graphql
type ProductServing {
name: String
price: Float
}
type ProductDish {
price: Float
calories: Int
servings: [ProductServing]
}
type ProductDrink {
price: Float
servings: [ProductServing]
}
union ProductProperties = ProductDish | ProductDrink
type Product {
id: ID!
user: User! @belongsTo
media: Media
blocks: [Block]! @belongsToMany
slug: String!
name: String!
description: String
properties: ProductProperties!
activated_at: DateTime
created_at: DateTime!
updated_at: DateTime!
}
Of course this schema alone wont work because Lighthouse cannot understand the custom type. I've created two classes for Types:
// App\GraphQL\Types
class ProductDish extends ObjectType
{
public function __construct()
{
$config = [
"name" => "ProductDish",
"fields" => [
"__type" => Type:string(),
"price" => Type::float(),
"calories" => Type::int(),
],
];
parent::__construct($config);
}
}
class ProductDrink extends ObjectType
{
public function __construct()
{
$config = [
"name" => "ProductDrink",
"fields" => [
"__type" => Type:string(),
"price" => Type::float(),
],
];
parent::__construct($config);
}
}
And a union class for ProductProperties which use the __invoke method
// App\GraphQL\Unions;
public function __invoke($rootValue, GraphQLContext $context, ResolveInfo $resolveInfo) : Type
{
$type = $rootValue["__type"];
switch ($type) {
case "dish" :
return $this->typeRegistry->get(ProductDish::class);
case "drink":
return $this->typeRegistry->get(ProductDrink::class);
}
return $this->typeRegistry->get(class_basename($rootValue));
}
This doesn't work, otherwise I wouldn't be here, looking at the graphql-playground I get this message
"debugMessage": "Lighthouse failed while trying to load a type: App\\GraphQL\\Types\\ProductDish\n\nMake sure the type is present in your schema definition.\n"
The thing is that I'm not sure if 1) this is the right approach 2) why lighthouse can't load the type.
Can you show me the correct way of handling this?
Bear in mind that
I was on the right track but I needed to fix some things
First, inside ProductProperties
file the registry expect a simple string not a namespace so I had to type ->get("ProductDish")
instead of ->get(ProductDish::class)
then I removed the __type
field inside my types, and graphql schemas because I can use a mutator inside Product
model and determine which type is based on some parameters, something like this
public function getPropertisAttribute($properties) {
$properties = json_decode($properties, true);
$properties["__type"] = // .. some logic to get the right type
return $properties;
}
Once I've a type I can use that back into my ProductProperties
union class