Interactie met de GraphQL API
Interactie met de GraphQL APIVerwerken van mutation payloads

Verwerken van mutation payloads

Mutatievelden kunnen worden geconfigureerd om een van deze 2 verschillende entiteitstypen te retourneren:

  • Een payload-objecttype
  • Rechtstreeks de gemuteerde entiteit

Payload-objecttype

Een payload-objecttype bevat alle gegevens met betrekking tot de mutation:

  • De status van de mutation (succes of mislukking)
  • De fouten (indien aanwezig) met behulp van onderscheidende GraphQL-typen, of
  • De succesvol gemuteerde entiteit

Zo retourneert de mutation updatePost een object van het type PostUpdateMutationPayload, en we moeten nog steeds het veld post opvragen om de bijgewerkte post-entiteit op te halen:

mutation UpdatePost {
  updatePost(input: {
    id: 1724,
    title: "New title",
    status: publish
  }) {
    # This is the status of the mutation: SUCCESS or FAILURE
    status
    errors {
      __typename
      ...on ErrorPayload {
        message
      }
    }
    post {
      id
      title
      # This is the status of the post: publish, pending, trash, etc
      status
    }
  }
}

Het payload-object stelt ons in staat om fouten beter weer te geven, en zelfs een uniek GraphQL-type per soort fout te hebben. Hierdoor kunnen we verschillende reacties voor verschillende fouten in de applicatie presenteren, wat de gebruikerservaring verbetert.

In het bovenstaande voorbeeld, als de bewerking geslaagd is, ontvangen we:

{
  "data": {
    "updatePost": {
      "status": "SUCCESS",
      "errors": null,
      "post": {
        "id": 1724,
        "title": "Some title",
        "status": "publish"
      }
    }
  }
}

Als de gebruiker niet is ingelogd, ontvangen we:

{
  "data": {
    "updatePost": {
      "status": "FAILURE",
      "errors": [
        {
          "__typename": "UserIsNotLoggedInErrorPayload",
          "message": "You must be logged in to create or update custom posts"
        }
      ],
      "post": null
    }
  }
}

Als de gebruiker geen toestemming heeft om posts te bewerken, ontvangen we:

{
  "data": {
    "updatePost": {
      "status": "FAILURE",
      "errors": [
        {
          "__typename": "LoggedInUserHasNoEditingCustomPostCapabilityErrorPayload",
          "message": "Your user doesn't have permission for editing custom posts."
        }
      ],
      "post": null
    }
  }
}

In deze modus bevat het GraphQL-schema veel aanvullende MutationPayload-, MutationErrorPayloadUnion- en ErrorPayload-typen, waardoor het een grotere omvang heeft:

GraphQL-schema met payload-objecttypen voor mutations

De mutation payload-objecten opvragen

Elke mutation in het schema heeft een overeenkomstig veld om de onlangs aangemaakte payload-objecten op te vragen, met de naam {mutationName}MutationPayloadObjects.

Deze velden omvatten:

  • addCommentToCustomPostMutationPayloadObjects (voor addCommentToCustomPost)
  • createCustomPostMutationPayloadObjects (voor createCustomPost)
  • createMediaItemMutationPayloadObjects (voor createMediaItem)
  • createPageMutationPayloadObjects (voor createPage)
  • createPostMutationPayloadObjects (voor createPost)
  • removeFeaturedImageFromCustomPostMutationPayloadObjects (voor removeFeaturedImageFromCustomPost)
  • replyCommentMutationPayloadObjects (voor replyComment)
  • setCategoriesOnPostMutationPayloadObjects (voor setCategoriesOnPost)
  • setFeaturedImageOnCustomPostMutationPayloadObjects (voor setFeaturedImageOnCustomPost)
  • setTagsOnPostMutationPayloadObjects (voor setTagsOnPost)
  • updateCustomPostMutationPayloadObjects (voor updateCustomPost)
  • updatePageMutationPayloadObjects (voor updatePage)
  • updatePostMutationPayloadObjects (voor updatePost)

Deze velden stellen ons in staat om de resultaten op te halen van mutations die zijn uitgevoerd met @applyField terwijl we de items in een array doorlopen.

Zo dupliceert de volgende query posts in bulk:

query GetPostsAndExportData
{
  postsToDuplicate: posts {
    title
    rawContent
    excerpt
 
    # Already create (and export) the inputs for the mutation
    postInput: _echo(value: {
      title: $__title
      contentAs: {
        html: $__rawContent
      },
      excerpt: $__excerpt
    })
      @export(as: "postInput", type: LIST)
      @remove
  }
}
 
mutation CreatePosts
  @depends(on: "GetPostsAndExportData")
{
  createdPostMutationPayloadObjectIDs: _echo(value: $postInput)
    @underEachArrayItem(
      passValueOnwardsAs: "input"
    )
      @applyField(
        name: "createPost"
        arguments: {
          input: $input
        },
        setResultInResponse: true
      )
    @export(as: "createdPostMutationPayloadObjectIDs")
}
 
query DuplicatePosts
  @depends(on: "CreatePosts")
{
  createdPostMutationObjectPayloads: createPostMutationPayloadObjects(input: {
    ids: $createdPostMutationPayloadObjectIDs
  }) {
    status
    errors {
      __typename
      ...on ErrorPayload {
        message
      }
    }
    post {
      id
      title
      rawContent
      excerpt
    }
  }
}

Standaard worden deze velden niet toegevoegd aan het GraphQL-schema. Daarvoor moeten we de optie "Use payload types for mutations, and add fields to query those payload objects" selecteren.

Gemuteerde entiteit

De mutation retourneert bij succes rechtstreeks de gemuteerde entiteit, of null bij mislukking, en eventuele foutmeldingen worden weergegeven in het errors-item op het hoogste niveau van het JSON-antwoord.

Zo retourneert de mutation updatePost het object van het type Post:

mutation UpdatePost {
  updatePost(input: {
    id: 1724,
    title: "New title",
    status: publish
  }) {
    id
    title
    status
  }
}

Als de bewerking geslaagd is, ontvangen we:

{
  "data": {
    "updatePost": {
      "id": 1724,
      "title": "Some title",
      "status": "publish"
    }
  }
}

In geval van fouten verschijnen deze onder het errors-item van het antwoord. Als de gebruiker bijvoorbeeld niet is ingelogd, ontvangen we:

{
    "errors": [
      {
        "message": "You must be logged in to create or update custom posts'",
        "locations": [
          {
            "line": 2,
            "column": 3
          }
        ]
      }
  ],
  "data": {
    "updatePost": null
  }
}

We moeten opmerken dat het errors-item op het hoogste niveau hierdoor niet alleen syntaxis-, schemavalidatie- en logicafouten bevat (bijv.: geen naam opgeven voor een veldargument, een niet-bestaand veld opvragen, of _sendHTTPRequest aanroepen terwijl het netwerk niet beschikbaar is), maar ook "inhoudsvalidatie"-fouten (bijv.: "je hebt geen toestemming om dit bericht te wijzigen").

Omdat er geen aanvullende typen worden toegevoegd, ziet het GraphQL-schema er overzichtelijker uit:

GraphQL-schema zonder payload-objecttypen voor mutations

Het payload-objecttype voor mutations verwerken

Laten we eens kijken hoe we de eerste optie, het payload-objecttype, kunnen afhandelen.

Mutations in het schema retourneren een payload-object dat eventuele fout(en) als gevolg van de mutation verschaft, of het gewijzigde object bij succes (deze 2 eigenschappen zijn hoogstwaarschijnlijk exclusief: ofwel errors ofwel object heeft een waarde, en de andere is null).

Fouten worden geleverd via een "ErrorPayloadUnion"-type, dat alle mogelijke fouten voor die mutation bevat. Elke mogelijke fout is een "ErrorPayload"-type dat de interface ErrorPayload implementeert.

Zo retourneert de bewerking updatePost een PostUpdateMutationPayload, die de volgende velden bevat:

  • status: of de bewerking geslaagd is of niet, met de waarde SUCCESS of FAILURE
  • post en postID: het bijgewerkte post-object en het ID ervan, als de update geslaagd is
  • errors: een lijst van CustomPostUpdateMutationErrorPayloadUnion, als de update mislukt is.

Het union-type CustomPostUpdateMutationErrorPayloadUnion bevat de lijst van alle mogelijke fouten die kunnen optreden bij het wijzigen van een custom post:

  • CustomPostDoesNotExistErrorPayload
  • GenericErrorPayload
  • LoggedInUserHasNoEditingCustomPostCapabilityErrorPayload
  • LoggedInUserHasNoPermissionToEditCustomPostErrorPayload
  • LoggedInUserHasNoPublishingCustomPostCapabilityErrorPayload
  • UserIsNotLoggedInErrorPayload

Het fouttype GenericErrorPayload is opgenomen in alle "ErrorPayloadUnion"-typen. Het wordt gebruikt wanneer de specifieke reden voor de fout niet kan worden aangewezen, zoals wanneer wp_update_post simpelweg WP_Error produceert. Dit type biedt twee extra velden: code en data.

Vervolgens kunnen we de volgende mutation uitvoeren om updatePost uit te voeren:

mutation UpdatePost(
  $postId: ID!
  $title: String!
) {
  updatePost(
    input: {
      id: $postId,
      title: $title,
    }
  ) {
    status
    errors {
      __typename
      ...on ErrorPayload {
        message
      }
      ...on GenericErrorPayload {
        code
      }
    }
    post {
      id
      title
    }
  }
}

Als de bewerking geslaagd is, ontvangen we:

{
  "data": {
    "updatePost": {
      "status": "SUCCESS",
      "errors": null,
      "post": {
        "id": 1724,
        "title": "This incredible title"
      }
    }
  }
}

Als de gebruiker niet is ingelogd, ontvangen we:

{
  "data": {
    "updatePost": {
      "status": "FAILURE",
      "errors": [
        {
          "__typename": "UserIsNotLoggedInErrorPayload",
          "message": "You must be logged in to create or update custom posts"
        }
      ],
      "post": null
    }
  }
}

Als de gebruiker geen toestemming heeft om posts te bewerken, ontvangen we:

{
  "data": {
    "updatePost": {
      "status": "FAILURE",
      "errors": [
        {
          "__typename": "LoggedInUserHasNoEditingCustomPostCapabilityErrorPayload",
          "message": "Your user doesn't have permission for editing custom posts."
        }
      ],
      "post": null
    }
  }
}