3

I am working on a custom module in which I've implemented graphql. One of the key in response contains different fields. For example, in the below json response the dynamic_fields content will depend on item_type and will be different.

"response" : {
    "items": {
        "item_id" : 1,
        "item_type" : "custom1"
        "dynamic_fields": {
            "custom_field1" : "data1"
            "custom_field2" : "data2"
        },
        "item_id" : 2,
        "item_type" : "custom2"
        "dynamic_fields": {
            "custom_field3" : "data3"
            "custom_field4" : "data4"
        },

    }
}

Can it be implemented using typeResolver? How to use typeResolver with TypeResolverInterface? Can it be used for dynamic types with inline fragmens?

Thanks in advance.

3 Answers 3

2

A TypeResolver helps to decide which type a concrete value belongs to. This is needed for Interface. For example imagine you have an Interface called DashboardOutputInterface which resolves back to a series of classes called BannerSlider, CategorySlider and ProductSlider. The type resolver is responsible for examining a runtime object and deciding what GraphqlObjectType should be used to represent it, and hence what data fetchers and fields will be invoked.

CompanyName/ModuleName/etc/schema.graphqls

type Query {
    dashboard : [DashboardOutputInterface] @resolver( class: "CompanyName\\ModuleName\\Model\\Resolver\\Dashboard")
}
interface DashboardOutputInterface @typeResolver(class: "CompanyName\\ModuleName\\Model\\Resolver\\CustomTypeResolverComposite") {
    block_id: Int @doc(description: "Block Id")
    block_type: String @doc(description: "Block Type")
    position: Int @doc(description: "Position")
}
type BannerSlider implements DashboardOutputInterface {
    id: Int
    image: String
}
type ProductSlider implements DashboardOutputInterface {
    id: Int
    products: [ProductInterface]
}
type CategorySlider implements DashboardOutputInterface {
    id: Int
    categories: [CategoryInterface]
}

CompanyName\ModuleName\Model\Resolver\CustomTypeResolverComposite

public function resolveType(array $data) : string
{
    if (isset($data['block_type'])) {
        if ($data['block_type'] == 'category_slider') {
            return 'CategorySlider';
        } elseif ($data['block_type'] == 'product_slider') {
            return 'ProductSlider';
        } elseif ($data['block_type'] == 'banner_slider') {
            return 'BannerSlider';
        }
    }
    throw new GraphQlInputException(
        __('Concrete type for %1 not implemented', ['DashboardOutputInterface'])
    );
}

Your query look like

query getDashboard {
  dashboard {    
    block_id
    block_type    
    position
    __typename
    ...CategorySliderFragement
    ...ProductSliderFragement
    ...BannerSliderFragement
  }
}
fragment CategorySliderFragement on CategorySlider {  
    id
    categories {
        id
        name
    }
}
fragment ProductSliderFragement on ProductSlider {  
    id
    products {
        id
        name
    }
}
fragment BannerSliderFragement on BannerSlider {  
    id
    image
}
0

You can define a resolver for any custom type field you declare. Looks here like you may be extending the existing items type? Presuming this is either the items type defined in the cart query ([CartItemInterface]) or maybe the items type defined in the products query ([ProductInterface])?

If either of those assumptions is correct, seems like you may have to add a new type to either CartItemInterface/ProductInterface and declare a resolver for them within the schema file. More info in regards to this can be found here in dev docs:

1
  • Thanks for writing, but I need detailed explanation on it and a code example would be appreciated. I've already gone through the above documentation but not able to implement it practically. Apr 19, 2022 at 10:34
0

First, all types must be declared in the schema. If the sub-types of dynamic_fields are subject to change (custom_field1,custom_field2 etc) then you might have to declare these as a key/value return type? Where the key is the attribute code and the value is the attribute value

type DynamicFieldOutput { 
    key: String 
    value: String 
} 

Then, you may want to define a resolver on the dynamic_fields field. This resolver will return the key/value output defined above. The resolver must implement \Magento\Framework\GraphQl\Query\ResolverInterface. You should be able to access the product model via $value['model'] in the resolve function implemented via the interface.

interface ProductInterface {
    dynamic_fields: [DynamicFieldOutput] @resolver (class: "\\Namespace\\Module\\Model\\Resolver\\DynamicFieldResolver")
}

type DynamicFieldOutput {
    key: String
    value: String
}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.