Table of Contents & Menu
Navigation

Customizing GraphQL

Hyvä themes use GraphQL for various features (e.g., cart page). When you need to customize these queries—like adding fields or changing arguments—you can do so via Magento event observers, avoiding template overrides or view model modifications. This functionality is provided by the hyva-themes/magento2-graphql-view-model.

How it works

The hyva-themes/magento2-graphql-view-model module, while primarily used in Hyvä, is open-source and can be integrated into any Magento theme.

How queries are made “editable”

GraphQL queries and mutations in .phtml templates are made editable by wrapping them in the GraphqlViewModel::query() method. See this simplified example:

<?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 accepts three arguments:

  • The first argument, $queryIdentifier, is the event name suffix.
  • The second argument, $query, is the GraphQL 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_. For the example above, the full event name is hyva_graphql_render_before_product_list_query.

How to edit queries and mutations

Use the \Hyva\GraphqlViewModel\Model\GraphqlQueryEditor within an event observer to manipulate queries. It provides two methods:

  • addFieldIn(string $query, array $path, string $field)
  • addArgumentIn(string $query, array $path, string $key, $value)

Both methods share similar signatures:

  • 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.

Both methods return the modified 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);
}

This addFieldIn call:

$gqlEditor->addFieldIn(
    $queryString,
    ['products', 'items', 'products', 'small_image'],
    'label url_webp'
)

will add label and url_webp to the small_image object within the query, alongside any existing fields. The resulting query structure will include:

products {
  items {
    products {
      small_image {
        label
        url_webp
      }
    }
  }
}

Both addFieldIn and addArgumentIn are idempotent; they won't alter existing values if they match. addArgumentIn can add new arguments or overwrite existing ones. For more advanced examples, including inline fragments, refer to the test cases in \Hyva\GraphqlViewModel\Model\GraphqlQueryEditorTest.