Blog

🛠 WordPress dovrebbe avere un'API GraphQL nel core?

Leonardo Losoviz
Di Leonardo Losoviz ·

Aggiornamento 01/05/2024: Dai un'occhiata al confronto Gato GraphQL vs WP REST API.

WordPress 5.7 arriverà presto. Come accade ormai da molte versioni, anche la WP REST API porterà diverse nuove funzionalità.

Tra le nuove funzionalità, una ha attirato la mia attenzione: "Image Editor Accepts a List of Modifiers".

L'endpoint /wp/v2/media/<id>/edit introdotto in WordPress 5.5 era dotato di un'API limitata che accettava dichiarazioni di rotazione e ritaglio di livello superiore. In 50124 questa API è stata resa più potente e flessibile accettando un array di modifiche nel nuovo parametro di richiesta 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' } );

Questo sviluppo ha richiesto del tempo per essere realizzato.

Innanzitutto, in WordPress 5.5, è stato introdotto l'endpoint di modifica delle immagini.

Questo endpoint era inizialmente piuttosto rigido, richiedendo di passare insieme tutti i dati relativi a tutte le operazioni da applicare sull'immagine. Ad esempio, per ruotare l'immagine e modificarne le dimensioni, avremmo passato questi dati:

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

Successivamente, in WordPress 5.6, le operazioni in batch sono state introdotte nella WP REST API.

Infine, nella prossima versione WordPress 5.7, le operazioni da applicare sull'immagine sono state disaccoppiate, così abbiamo le operazioni "crop" e "rotate". Queste operazioni possono essere eseguite separatamente, ma anche insieme nella stessa richiesta tramite il batching.

Come visto in precedenza, passare i dati all'endpoint ora appare molto più elegante:

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

Rifare ciò che esiste già?

La WP REST API non è l'unica API per WordPress. Esistono (almeno) due alternative:

  • GraphQL, tramite WPGraphQL
  • GraphQL + persisted queries, tramite Gato GraphQL
    (☝🏽 Sono io, il tuo padrone di casa per questo articolo del blog ☝🏽)

GraphQL è un tipo di API relativamente nuovo, che eccelle nelle operazioni in batch. Usando GraphQL, non c'è bisogno di spendere tempo ed energie per sviluppare una soluzione personalizzata per esse, come accade invece con REST.

Infatti, si potrebbe vedere REST come se "copiasse" questa funzionalità da GraphQL.

REST che copia GraphQL?

Supportare le operazioni in batch nella WP REST API ha richiesto almeno 2, forse 3, cicli di rilascio per essere realizzato. Non è una quantità di tempo trascurabile, e ha richiesto il contributo di diverse persone.

Se WordPress potesse anche utilizzare GraphQL, e l'endpoint di modifica delle immagini fosse basato su GraphQL invece che su REST, allora questi contributori potrebbero lavorare su altri sviluppi.

WordPress non starebbe meglio, e non verrebbe sviluppato molto più velocemente, se potesse utilizzare le migliori qualità di ciascuna API, ogni volta che è conveniente?

Operazioni in batch in GraphQL

Ti mostrerò non uno, ma diversi modi in cui Gato GraphQL supporta le operazioni in batch.

Il primo è il più semplice: aggiungere diversi campi alla radice della query. Ad esempio, questa query effettua il login dell'utente e poi aggiunge un commento:

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
  }
}

(A proposito, questo è il client GraphiQL. Ecco un tutorial sul suo utilizzo.)

Queste due operazioni sono state applicate su oggetti diversi, ma vogliamo applicare diverse operazioni sullo stesso oggetto.

Facciamolo ora: questa query aggiunge due commenti allo stesso articolo.

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
  }
}

Questi due commenti sono stati aggiunti a un articolo già esistente. Ma cosa succederebbe se l'articolo dovesse anche essere creato per primo?

In tal caso, la query semplice non funzionerà più, perché non conosciamo l'ID dell'articolo ancora da creare, che è necessario come argomento per le altre operazioni (nota il ? nell'argomento del campo):

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
  }
}

Ma non disperare, Gato GraphQL ti copre le spalle. Offre non una, ma due soluzioni!

L'API GraphQL si prende cura di te

La prima consiste nell'utilizzare la funzionalità di esecuzione di query multiple.

In questa query, eseguiamo la prima operazione, esportiamo il suo risultato tramite la direttiva @export, e poi iniettiamo questo valore come input nella seconda query:

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
    }
  }
}

Ancora più elegante, possiamo utilizzare le mutation annidate.

In questa query, eseguiamo la prima operazione e annidiamo la seconda operazione al suo interno, in modo che venga applicata all'oggetto creato durante la prima operazione (e poi ripetiamo, annidando una 3ª operazione, e così via):

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
        }
      }
    }
  }
}

Come bonus, le operazioni in batch possono essere applicate non solo su una singola entità, ma su molte entità contemporaneamente, nella stessa richiesta.

In questa query, i nuovi commenti e tutte le loro risposte vengono aggiunti a diversi articoli:

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
        }
      }
    }
  }
}

E il plugin ha ancora un altro asso nella manica: utilizzando la funzionalità dei campi incorporabili, possiamo personalizzare il contenuto passato a ciascun argomento di campo, usando i dati dell'oggetto stesso!

In questa query, i commenti contengono informazioni dell'oggetto su cui vengono creati:

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
        }
      }
    }
  }
}

Ottenere il meglio da REST e GraphQL quando è conveniente

Man mano che Full Site Editing viene sviluppato ed esteso, WordPress dipenderà sempre più dalle sue API.

Per quanto riguarda le funzionalità esistenti, la REST API si è comportata molto bene finora. Non c'è bisogno di ricostruire ciò che non è rotto.

Tuttavia, per quanto riguarda le nuove funzionalità ancora da sviluppare, WordPress non trarrebbe beneficio dall'utilizzo di REST o GraphQL, a seconda di ciò che è più conveniente per quella specifica funzionalità?

La risposta spetta a te...

Qual è la tua opinione?


Iscriviti alla nostra newsletter

Resta aggiornato su tutte le novità di Gato GraphQL.