Skip to content

Instantly share code, notes, and snippets.

@paliarush
Last active February 15, 2023 14:36
Show Gist options
  • Save paliarush/dda94121eb19bf09b20ff366aa7e597d to your computer and use it in GitHub Desktop.
Save paliarush/dda94121eb19bf09b20ff366aa7e597d to your computer and use it in GitHub Desktop.
[POLL] LEVERAGING SERVICE INTERFACES IN DECLARATIVE GRAPHQL SCHEMA
Magento GraphQL endpoints must support EAV entities such as Products. GraphQL specification requires all complex types eventually to be represented as structures of scalar types. Mixed/any types are not supported.
We have couple options to choose from and would be glad to hear your opinion on that.
==============
*Option 1: Custom attributes container*
*Schema*
NOTE: Parts of the schema which are identical in both options are omitted.
```
interface CustomAttribute {
attribute_code: String!
}
type StringAttribute implements Attribute {
attribute_code: String!
attribute_value: String!
}
type IntAttribute implements Attribute {
attribute_code: String!
attribute_value: Int!
}
type BooleanAttribute implements Attribute {
attribute_code: String!
attribute_value: Boolean!
}
type FloatAttribute implements Attribute {
attribute_code: String!
attribute_value: Float!
}
type MediaAttribute implements Attribute {
attribute_code: String!
attribute_value: MediaAttributeValue!
}
type MediaAttributeValue {
size: String!
path: String!
}
type Product {
id: Int
sku: String
custom_attributes(attribute_code: String!): [CustomAttribute]!
}
```
*Query*
```
product(filter: {
or: {
sku: {like:"%_2%"}
or: {
custom_attributes: [
{
code: “some_custom_attribute”,
value: “0”,
condition: “eq”
}
]
}
}
}
pageSize: 1
currentPage:1
) {
items{
id
sku
custom_attributes(attribute_code: "some_custom_attribute,another_custom_attribute") {
attribute_code
... on StringAttribute {
atribute_value
}
... on FloatAttribute {
atribute_value
}
... on BooleanAttribute {
atribute_value
}
... on IntAttribute {
atribute_value
}
... on MediaAttribute
{
atribute_value {
size
path
}
}
}
}
}
```
*Pros*
- Bag of attributes is a good OOP abstraction on the entities dynamically defined in the run-time
- Simple way to represent attribute sets
*Cons*
- Nested structure for custom attributes filters (filter name, condition, value).
No auto-complete for attribute names in filter and sorting.
- More complicated client code, requires GraphQL fragment declaration for every possible custom attribute value type.
- Requires special syntax for requesting specific attributes
- It is impossible to see all attributes available on the storefront in GraphQL schema, No auto-completion available in IDEs like Graphiql
=====================
*Option 2: Custom attributes in flat structure under the entity object*
In case when requested custom attributes are not defined for the resulting product, the values of such attributes will be set to null.
*Schema*
```
type SimpleProduct implements Product {
some_custom_attribute: Boolean
another_custom_attribute: MediaAttributeValue
id: Int
sku: String
}
type MediaAttributeValue {
size: String!
path: String!
}
```
*Query*
```
product(filter: {
or: {
sku: {like:"%_2%"}
or: {
some_custom_attribute: {eq: “0”}
}
}
}
pageSize: 1
currentPage:1
) {
items{
some_custom_attribute
another_custom_attribute
{
size,
path
}
id
sku
}
}
```
*Pros*
- Good semantics for filters
- You can see all available attributes in GraphQL schema
- Auto-complete works in query, filter and sorting
*Cons*
- Request must be generated (using Magento client library)
- Custom options are still represented as an array.
Do we need to request specific custom options or use them in filters?
- It is possible to request attributes un-related to the requested product's attribute set. The values will be set to NULL in the response
- Schema cache must be invalidated on every change to custom attributes (CRUD on EAV attributes). Minor issue since cache invalidation must be implemented anyway
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment