How it works?

Last updated on
4 September 2024

This documentation needs work. See "Help improve this page" in the sidebar.

Source options

Mandatory options are marked with a star (*).

The graphql source offers a number of options to allow you to best configure your query. In short:

source:
  plugin: graphql

  # [mandatory] The GraphQL endpoint
  endpoint: <value>
  # [optional] Basic, Bearer, Digest, etc...
  auth_scheme: <value>
  # [optional] Paired with auth_scheme will generate the string that 
  # will be passed to the Authorization header
  auth_parameter: <value>
  # [optional] Used to specify a different name for "data" property
  data_key: <value>
  # [optional] Source field to use as ID (if omitted will be "id" of "string" type)
  ids:
    <source_field_name>:
      type: <source_filed_type> # string, int, etc.
  # [mandatory] from here starts the query definition
  query:
    # [mandatory] The query name
    <query_name>:
      # [optional] Query arguments (filtering, pagination, and so on...). 
      # See the example below.
      arguments:
      # [mandatory] Query fields definition
      fields:
        # [mandatory] It is 'data' if no different value has been set in data_key
        - <data|data_key>:
            - <field_1>
            - <field_2>
            - <field_n>
  
  • endpoint*: Represents the GraphQL endpoint.

  • Authentication

    • auth_scheme: Specify different authorization schemes like Basic, Bearer, Digest (etc...);

    • auth_parameter: Simply pairing the auth_scheme and auth_parameters value, will generate the string that will be passed to the Authorization header. So, as example:

      • auth_scheme: Bearer
        auth_parameter: 'eyJhbGciO.eyJzdWIiOiIxMjM0NTY3...'

        will generate the following Authorization header: Authorization: Bearer eyJhbGciO.eyJzdWIiOiIxMjM0NTY3...

  • data_key: Specify a different name for "data" property. By default the data key's name is "data". It also accepts the Row::PROPERTY_SEPARATOR (/) to navigate nested structures, including iterator placeholder '%' for dynamic mapping. Get more information by reading "The data_key" section of documentation.

  • ids: Specify what source's filed represents the item ID. It's possible to configure its name (<source_field_name>) and its type (<source_field_type>). If this option is omitted will be automatically used "id" as <source_field_name> and "string" as <source_field_type>. Example:

    •   data_key: items
        query:
          schools:
            fields:
              - items:
                  - acronym
                  - msdeReport
        ids:
          acronym:
            type: string
  • query*: from here starts the query definition.

  • arguments: used to specify query arguments. It simply needs to be transposed the graphql into the yaml format.

    • query:
        posts:
          arguments:
            options:
              paginate:
                page: 1
                limit: 10
            fields: ...

      that in GraphQL become:

    • query {
        posts(options:{
          paginate: {
            page:1,
            limit:10
          }
        }) { ... }
  • fields*: The only difference between the GraphQL query and the YAML transposition is the mandatory property fields, the usefulness of which is solely a matter of choice for the developer.
  • ids: Allows to configure custom IDs in the GraphQL source plugin for migrations, similar to the existing functionality in the migrate_plus URL source plugin. This allows users to specify IDs that are not simply called "id". If not specified it will be "id" of "string" type. An example:
      query:
        schools:
          fields:
            - items:
                - acronym
                - msdeReport
      ids:
        acronym:
          type: string
    

The data_key

Specify a different name for the "data" property. By default the data key's name is "data". But, in some cases, it may need to go deeper instead of stopping at the first level of the structure. As example, let's take the following query:

query:
    posts:
      fields:
        -
          anotherBrickInTheWall:
            posts:
               - id
               - title
               - body

now suppose we want to get all the posts inside anotherBrickInTheWall, using data_key property we can do as follow:

data_key: anotherBrickInTheWall/posts

We used the PROPERTY_SEPARATOR (/) to get nested posts items.

Iterator placeholder '%':

  •  Example: data_key: data/%/user (follow below explanation)

Another case should be the following, imagine we have the following query:

...
query:
  albums:
    fields:
      -
        data:
          -
            user:
              - id
              - name
              - email

That will generate a response like this:

To map the properties of the 'user' item (id, name, email) onto the Drupal entity:user entity, you need to use data_key combined with the '%' placeholder like this: data_key: data/%/users.

Each time the migration loops through the response's results, it will check for the '%' placeholder, which represents an index (0, 1, ..., number of items). This allows it to access the internal 'user' items in the array. For example, it will first access $data[0]['user'], then $data[1]['user'], next $data[2]['user'], and so on.

In summary, using the '%' placeholder instructs the migration to retrieve the 'user' item within the array, rather than the element containing it.

An example

For this example we will use the GraphQLZero (Fake Online GraphQL API for Testing and Prototyping) from which we will migrate some entities, that on GraphQLZero are called posts, into the our Drupal instance populating the our's default articles.

Follow GraphQL query shows how to get a list of posts from GraphQLZero:

query {
  posts {
    data {
      id
      title
      body
    }
  }
}

The response:
GraphQL Zero

The migration

So we, as first thing, have to setup the YAML migration file. As like as follow:

id: migrate_graphql_posts_articles
label: 'Migrate posts from GraphQLZero'
migration_tags: null
source:
  plugin: graphql

  endpoint: 'https://graphqlzero.almansi.me/api'
  auth_scheme: Bearer
  auth_parameter: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3...'
  query:
    posts:
      fields:
        -
          data:
            - id
            - title
            - body
  ids:
    id:
      type: string
process:
  title: title
  body: body

destination:
  plugin: 'entity:node'
  default_bundle: article

migration_dependencies: {  }

The only difference between the GraphQL query and the YAML transposition is the mandatory property fields, the usefulness of which is solely a matter of choice for the developer.

This is what you should expect at the end of the migration:
Post imported

ResultsEvent for Data Manipulation

Starting from version 2.1.0, the Migrate Source GraphQL module introduces the ResultsEvent, allowing other modules to modify the results obtained from a GraphQL query during migration.

Key Features

  • getResults(): Retrieves the current query results.
  • setResults(array $results): Allows modification of these results.

Usage Example

Modules can subscribe to the ResultsEvent to manipulate the migration data:

use Drupal\migrate_source_graphql\Event\ResultsEvent;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;

class MyModuleSubscriber implements EventSubscriberInterface {
  public static function getSubscribedEvents() {
    return [ResultsEvent::class => 'onResultsEvent'];
  }

  public function onResultsEvent(ResultsEvent $event) {
    $results = $event->getResults();
    // Custom modifications to results.
    $results['custom_field'] = 'custom_value';
    $event->setResults($results);
  }
}

The GraphQL plugin now dispatches this event, enabling custom data handling during migrations.

Help improve this page

Page status: Needs work

You can: