Customizing GraphQL
The Hyvä default theme uses GraphQL queries occasionally, for example on the cart page.
The queries and mutations are built either in the templates or in view models like \Hyva\Theme\ViewModel\Cart\GraphQlQueriesWithVariables
.
Often customizations require adding new fields to the requested data, or changing or adding GraphQL arguments.
Instead of overriding the template or plugging into the view model methods, GraphQL queries can be changed using Magento event observers.
This is made possible by the hyva-themes/magento2-graphql-view-model.
How it works
The module is currently only used in Hyvä, but it can potentially be used in any Magento theme.
The view model is freely available as open source on GitHub.
How queries are made “editable”
In the .phtml
templates, queries and mutations are wrapped in the GraphqlViewModel::query()
method.
Here is a simplified query for example’s sake:
<?php $gqlViewModel = $viewModels->require(\Hyva\GraphqlViewModel\ViewModel\GraphqlViewModel::class); ?>
<?= $gqlViewModel->query("product_list_query", "
products(filter: {} pageSize: 20) {
items {
{$type}_products {
sku
id
small_image {
url
}
}
}
}", ['type' => $type])
?>
The GraphqlViewModel::query()
method takes three arguments.
- The first argument
$queryIdentifier
is the event name suffix. - The second argument
$query
is the query or mutation as a string. - The third argument
$eventParams
is optional and - if specified - will be merged into the Magento event arguments.
The event prefix is hyva_graphql_render_before_
.
In the above example. the full event name for the query is hyva_graphql_render_before_product_list_query
.
How to edit queries and mutations
To manipulate a query in an event observer, the \Hyva\GraphqlViewModel\Model\GraphqlQueryEditor
can be used.
The editor has two methods:
addFieldIn(string $query, array $path, string $field)
addArgumentIn(string $query, array $path, string $key, $value)
The method signatures are similar:
- The first argument is the query or mutation to edit.
- The second argument is the path into the request or argument object hierarchy
- The third argument is the field to add
- For
addArgumentIn
, the fourth argument is the value of the argument field.
They both return the changed GraphQL query string.
Example
Another Example
An additional example can be found in the FAQ topic Customizable options on configurable cart items.
public function execute(Observer $event)
{
$gqlEditor = new GraphqlQueryEditor(); // or use dependency injection
// Get the query or mutation from the event
$queryString = $event->getData('gql_container')->getData('query');
// Get additional data if available or required.
// The link type in this example is only available for product sliders
$linkType = $event->getData('type');
// The path into the query
$path = ['products', 'items', ($linkType ? "{$linkType}_products" : 'products'), 'small_image'];
// Add a field to the requested result object
$queryString = $gqlEditor->addFieldIn($queryString, $path, 'url_webp');
// Set updated query back on container
$event->getData('gql_container')->setData('query', $queryString);
}
The result of the method call
$gqlEditor->addFieldIn(
$queryString,
['products', 'items', 'products', 'small_image'],
'label url_webp'
)
is that in the query the fields at the specified path are set, in addition to any already existing fields.
Note that above two fields are being set within the small_image
object, so after that call at least the following fields will exist on the result:
Both the addFieldIn
and the addArgumentIn
methods are idempotent, so if the specified values already exist in the query string they are not changed.
The addArgumentIn
method can be used to add new arguments to queries or mutations, or to overwrite values of existing arguments.
For more examples including inline fragments please have a look at the test cases in \Hyva\GraphqlViewModel\Model\GraphqlQueryEditorTest
.