Blog

🛠 WordPress devrait-il avoir une API GraphQL dans le core ?

Leonardo Losoviz
Par Leonardo Losoviz ·

Mise Ă  jour 01/05/2024 : Consultez la comparaison Gato GraphQL vs WP REST API.

WordPress 5.7 arrive bientÎt. Comme c'est le cas depuis de nombreuses versions, la WP REST API apportera également plusieurs nouvelles fonctionnalités.

Parmi les nouvelles fonctionnalités, l'une a retenu mon attention : "Image Editor Accepts a List of Modifiers".

L'endpoint /wp/v2/media/<id>/edit introduit dans WordPress 5.5 Ă©tait livrĂ© avec une API limitĂ©e qui acceptait des dĂ©clarations de rotation et de recadrage de niveau supĂ©rieur. Dans 50124, cette API a Ă©tĂ© rendue plus puissante et flexible en acceptant un tableau de modifications dans le nouveau paramĂštre de requĂȘte modifiers.

import apiFetch from '@wordpress/api-fetch';
 
const data = {
  modifiers: [
    {
      type: 'crop',
      args: {
        left  : 0,
        top   : 0,
        width : 80,
        height: 80
      }
    },
    {
      type: 'rotate',
      args: {
        angle: 90
      }
    }
  ]
};
apiFetch( { data, method: 'POST', path: '/wp/v2/media/5/edit' } );

Ce développement a pris un certain temps.

D'abord, dans WordPress 5.5, l'endpoint d'édition d'images a été introduit.

Cet endpoint était initialement assez rigide, nécessitant de passer toutes les données ensemble concernant toutes les opérations à appliquer sur l'image. Par exemple, pour faire pivoter l'image et modifier sa taille, on passerait ces données :

{
  "x": 0,
  "y": 0,
  "width": 80,
  "height": 80,
  "rotate": 90
}

Ensuite, dans WordPress 5.6, les opérations en lot ont été introduites dans la WP REST API.

Enfin, dans la prochaine version WordPress 5.7, les opĂ©rations Ă  appliquer sur l'image ont Ă©tĂ© dĂ©couplĂ©es, nous avons donc les opĂ©rations "crop" et "rotate". Ces opĂ©rations peuvent ĂȘtre exĂ©cutĂ©es sĂ©parĂ©ment, mais aussi ensemble dans la mĂȘme requĂȘte via le traitement par lot.

Comme vu précédemment, passer des données à l'endpoint est maintenant beaucoup plus élégant :

{
  "modifiers": [
    {
      "type": "crop",
      "args": {
        "left"  : 0,
        "top"   : 0,
        "width" : 80,
        "height": 80
      }
    },
    {
      "type": "rotate",
      "args": {
        "angle": 90
      }
    }
  ]
}

Refaire ce qui existe déjà ?

La WP REST API n'est pas la seule API pour WordPress. Il existe (au moins) deux alternatives :

  • GraphQL, via WPGraphQL
  • GraphQL + persisted queries, via Gato GraphQL
    (â˜đŸœ C'est moi, votre hĂŽte pour cet article de blog â˜đŸœ)

GraphQL est un type d'API relativement récent, qui excelle dans les opérations en lot. En utilisant GraphQL, il n'est pas nécessaire de passer du temps et de l'énergie à développer une solution personnalisée pour celles-ci, comme c'est le cas avec REST.

En effet, on pourrait voir REST comme "copiant" cette fonctionnalité de GraphQL.

REST copiant GraphQL ?

Prendre en charge les opérations en lot dans la WP REST API a pris au moins 2, voire 3, cycles de version à accomplir. Ce n'est pas une quantité de temps négligeable, et cela a nécessité la contribution de plusieurs personnes.

Si WordPress pouvait également utiliser GraphQL, et que l'endpoint d'édition d'images était basé sur GraphQL plutÎt que sur REST, alors ces contributeurs pourraient travailler sur d'autres développements.

WordPress ne serait-il pas mieux loti, et développé beaucoup plus rapidement, s'il pouvait utiliser les meilleures qualités de chaque API, selon ce qui est le plus pratique ?

Opérations en lot dans GraphQL

Je vais vous montrer non pas une, mais plusieurs façons dont Gato GraphQL prend en charge les opérations en lot.

La premiĂšre est la plus simple : ajouter plusieurs champs Ă  la racine de la requĂȘte. Par exemple, cette requĂȘte connecte l'utilisateur, puis ajoute un commentaire :

mutation LogUserInAndAddCommentToPost {
  loginUser(
    by: { credentials: { usernameOrEmail: "test", password: "pass" } }
  ) {
    id
    name
  }
  addCommentToCustomPost(
    input: {
      customPostID: 1459
      commentAs: { html: "Adding a comment: bla bla bla" }
    }
  ) {
    id
    content
    date
  }
}

(Au fait, il s'agit du client GraphiQL. Voici un tutoriel sur son utilisation.)

Ces deux opĂ©rations ont Ă©tĂ© appliquĂ©es sur des objets diffĂ©rents, mais nous souhaitons appliquer plusieurs opĂ©rations sur le mĂȘme objet.

Faisons cela maintenant : cette requĂȘte ajoute deux commentaires au mĂȘme article.

mutation AddTwoCommentsToPost {
  firstComment: addCommentToCustomPost(
    input: {
      customPostID: 1459
      commentAs: { html: "This is my first response" }
    }
  ) {
    id
    content
    date
  }
  secondComment: addCommentToCustomPost(
    input: {
      customPostID: 1459
      commentAs: { html: "This is my second response" }
    }
  ) {
    id
    content
    date
  }
}

Ces deux commentaires ont Ă©tĂ© ajoutĂ©s Ă  un article dĂ©jĂ  existant. Mais que se passerait-il si l'article devait Ă©galement ĂȘtre créé en premier ?

Dans ce cas, la requĂȘte simple ne fonctionnera plus, car nous ne connaissons pas l'ID de l'article Ă  crĂ©er, qui est nĂ©cessaire comme argument pour les autres opĂ©rations (remarquez le ? dans l'argument du champ) :

mutation CreatePostAndAddTwoCommentsToPost {
  createPost(input: { title: "Some post" }) {
    id  # <= I don't know what this value will be
  }
  addCommentToCustomPost(input: {
    customPostID: ?,
    commentAs: { html: "Blah blah blah" }
  }) {
    id
    content
    date
  }
}

Mais ne désespérez pas, Gato GraphQL vous couvre. Il propose non pas une, mais deux solutions !

L'API GraphQL prend soin de vous

La premiĂšre consiste Ă  utiliser la fonctionnalitĂ© d'exĂ©cution de requĂȘtes multiples.

Dans cette requĂȘte, nous exĂ©cutons la premiĂšre opĂ©ration, exportons son rĂ©sultat via la directive @export, puis injectons cette valeur comme entrĂ©e dans la deuxiĂšme requĂȘte :

mutation AddComment {
  addCommentToCustomPost(
    customPostID: 1459
    commentAs: { html: "Some insightful comment" }
  ) {
    id @export(as: "newCommentID")
    content
    date
  }
}
 
mutation AddResponseToComment @depends(on: "AddComment") {
  replyComment(
    parentCommentID: $newCommentID
    commentAs: { html: "Debunking your insightful comment" }
  ) {
    id
    date
    content
    parent {
      id
    }
  }
}

Plus élégant encore, nous pouvons utiliser les mutations imbriquées.

Dans cette requĂȘte, nous exĂ©cutons la premiĂšre opĂ©ration et imbriquons la deuxiĂšme opĂ©ration Ă  l'intĂ©rieur, de sorte qu'elle sera appliquĂ©e Ă  l'objet créé lors de la premiĂšre opĂ©ration (puis en rĂ©pĂ©tant, en imbriquant une 3e opĂ©ration, et ainsi de suite) :

mutation AddCommentAndResponseAndResponse {
  addCommentToCustomPost(
    input: {
      customPostID: 1459
      commentAs: { html: "Some insightful comment" }
    }
  ) {
    id
    content
    date
    reply(input: { commentAs: { html: "Debunking your insightful comment" } }) {
      id
      date
      content
      parent {
        id
      }
      reply(input: { commentAs: { html: "No, it was right!" } }) {
        id
        date
        content
        parent {
          id
        }
      }
    }
  }
}

En bonus, les opĂ©rations en lot peuvent ĂȘtre appliquĂ©es non seulement sur une seule entitĂ©, mais sur plusieurs entitĂ©s en mĂȘme temps, dans la mĂȘme requĂȘte.

Dans cette requĂȘte, les nouveaux commentaires et toutes leurs rĂ©ponses sont ajoutĂ©s Ă  plusieurs articles :

mutation AddCommentAndResponseToManyPosts {
  posts(ids: [1657, 1153, 1499, 1459]) {
    id
    addComment(input: { commentAs: { html: "Some insightful comment" } }) {
      id
      content
      date
      reply(
        input: { commentAs: { html: "Debunking your insightful comment" } }
      ) {
        id
        date
        content
        parent {
          id
        }
      }
    }
  }
}

Et le plugin a encore un tour dans sa manche : en utilisant la fonctionnalitĂ© de champs intĂ©grables, nous pouvons personnaliser le contenu passĂ© Ă  chaque argument de champ, en utilisant les donnĂ©es de l'objet lui-mĂȘme !

Dans cette requĂȘte, les commentaires contiennent des informations de l'objet sur lequel ils sont créés :

mutation AddCustomCommentAndResponseToManyPosts {
  posts(ids: [1657, 1153, 1499, 1459]) {
    id
    addComment(
      input: {
        commentAs: { html: "The post has ID {{ id }} and title {{ title }}" }
      }
    ) {
      id
      content
      date
      reply(
        input: {
          commentAs: {
            html: "The parent comment was posted on {{ dateStr(format: \"d/m/Y\") }}. Cool, right?"
          }
        }
      ) {
        id
        date
        content
        parent {
          id
        }
      }
    }
  }
}

Tirer le meilleur de REST et GraphQL selon les besoins

À mesure que Full Site Editing est dĂ©veloppĂ© et Ă©tendu, WordPress dĂ©pendra de plus en plus de ses API.

Concernant les fonctionnalités existantes, la REST API s'est trÚs bien comportée jusqu'à présent. Il n'est pas nécessaire de reconstruire ce qui fonctionne.

Cependant, concernant les nouvelles fonctionnalités encore à développer, WordPress ne bénéficierait-il pas de l'utilisation de REST ou GraphQL, selon ce qui est le plus pratique pour cette fonctionnalité spécifique ?

La réponse vous appartient...

Quelle est votre opinion ?


Abonnez-vous Ă  notre newsletter

Restez au courant de toutes les nouveautés de Gato GraphQL.