Blog

🛠 Czy WordPress powinien mieć API GraphQL w rdzeniu?

Leonardo Losoviz
Autor: Leonardo Losoviz ·

Aktualizacja 01/05/2024: Sprawdź porównanie Gato GraphQL vs WP REST API.

WordPress 5.7 wkrótce zostanie wydany. Jak to bywa od wielu wersji, WP REST API również przyniesie kilka nowych funkcji.

Spośród nowych funkcji jedna przykuła moją uwagę: "Image Editor Accepts a List of Modifiers".

Endpoint /wp/v2/media/<id>/edit wprowadzony w WordPress 5.5 posiadał ograniczone API, które akceptowało deklaracje rotacji i przycinania na najwyższym poziomie. W 50124 API zostało rozbudowane i uelastycznione poprzez akceptowanie tablicy modyfikacji w nowym parametrze żądania 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' } );

Prace nad tym rozwiązaniem trwały przez jakiś czas.

Najpierw, w WordPress 5.5, wprowadzono endpoint do edycji obrazów.

Ten endpoint był początkowo dość sztywny — wymagał, aby wszystkie dane dotyczące wszystkich operacji na obrazie były przekazywane łącznie. Na przykład, aby obrócić obraz i zmienić jego rozmiar, przekazywalibyśmy takie dane:

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

Następnie, w WordPress 5.6, do WP REST API wprowadzono operacje wsadowe.

Wreszcie, w nadchodzącym WordPress 5.7, operacje na obrazie zostały rozdzielone, dzięki czemu mamy operacje "crop" i "rotate". Operacje te można wykonywać osobno, ale również razem w jednym żądaniu poprzez przetwarzanie wsadowe.

Jak widać powyżej, przekazywanie danych do endpointu wygląda teraz znacznie eleganciej:

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

Powtarzać to, co już istnieje?

WP REST API nie jest jedynym API dla WordPress. Istnieją (przynajmniej) dwie alternatywy:

  • GraphQL, przez WPGraphQL
  • GraphQL + utrwalone queries, przez Gato GraphQL
    (☝🏽 To ja, gospodarz tego wpisu na blogu ☝🏽)

GraphQL to stosunkowo nowy typ API, który wyróżnia się w operacjach wsadowych. Używając GraphQL, nie trzeba poświęcać czasu i energii na opracowywanie niestandardowego rozwiązania dla nich, jak ma to miejsce w przypadku REST.

Rzeczywiście, REST można postrzegać jako „kopiowanie" tej funkcji z GraphQL.

REST kopiuje GraphQL?

Obsługa operacji wsadowych w WP REST API zajęła co najmniej 2, a możliwe, że 3 cykle wydań. To niemała ilość czasu, a jej realizacja wymagała wkładu wielu osób.

Gdyby WordPress mógł również korzystać z GraphQL, a endpoint edycji obrazów bazował na GraphQL zamiast REST, ci twórcy mogliby pracować nad innymi rozwiązaniami.

Czy WordPress nie byłby lepszy i nie rozwijałby się znacznie szybciej, gdyby mógł korzystać z najlepszych cech każdego API, zawsze gdy jest to wygodne?

Operacje wsadowe w GraphQL

Pokażę nie jeden, ale kilka sposobów, w jakie Gato GraphQL obsługuje operacje wsadowe.

Pierwszy jest najprostszy: dodanie kilku pól do korzenia query. Na przykład ta query loguje użytkownika, a następnie dodaje komentarz:

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

(Przy okazji, to jest klient GraphiQL. Oto samouczek dotyczący jego użycia.)

Teraz obie te operacje zostały zastosowane na różnych obiektach, ale chcemy zastosować kilka operacji na tym samym obiekcie.

Zróbmy to dalej: ta query dodaje dwa komentarze do tego samego wpisu.

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

Te dwa komentarze zostały dodane do już istniejącego wpisu. Ale co by się stało, gdyby wpis również musiał być najpierw utworzony?

W takim przypadku prosta query nie zadziała, ponieważ nie znamy ID wpisu, który ma dopiero zostać utworzony, a który jest potrzebny jako argument dla innych operacji (zauważ ? w argumencie pola):

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

Ale nie martw się — Gato GraphQL ma wszystko pod kontrolą. Oferuje nie jedno, ale dwa rozwiązania!

API GraphQL dba o Ciebie

Pierwsze polega na użyciu funkcji wykonywania wielu queries.

W tej query wykonujemy pierwszą operację, eksportujemy jej wynik za pomocą dyrektywy @export, a następnie wstrzykujemy tę wartość jako dane wejściowe do drugiej 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
    }
  }
}

Jeszcze bardziej eleganckie jest użycie zagnieżdżonych mutacji.

W tej query wykonujemy pierwszą operację i zagnieżdżamy w niej drugą operację, tak aby była zastosowana na obiekcie utworzonym podczas pierwszej operacji (a następnie powtarzamy, zagnieżdżając 3. operację i tak dalej):

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

Jako bonus, operacje wsadowe można stosować nie tylko na jednej encji, ale na wielu encjach jednocześnie, w tym samym żądaniu.

W tej query nowe komentarze i wszystkie ich odpowiedzi są dodawane do wielu wpisów:

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

A plugin ma jeszcze jeden as w rękawie: używając funkcji osadzanych pól, możemy dostosować treść przekazywaną do każdego argumentu pola, korzystając z danych samego obiektu!

W tej query komentarze zawierają informacje o obiekcie, na którym są tworzone:

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

Czerpanie z REST i GraphQL tego, co najlepsze, zawsze gdy wygodne

W miarę jak Full Site Editing jest rozwijany i rozbudowywany, WordPress będzie coraz bardziej zależeć od swoich API.

Jeśli chodzi o istniejące funkcje, REST API radziło sobie do tej pory bardzo dobrze. Nie ma potrzeby przebudowywać tego, co działa.

Jednak w odniesieniu do nowych, jeszcze nieopracowanych funkcji — czy WordPress nie skorzystałby na możliwości używania REST lub GraphQL, zależnie od tego, co jest wygodniejsze dla danej funkcji?

Odpowiedź należy do Ciebie...

Jaka jest Twoja opinia?


Zapisz się do naszego newslettera

Bądź na bieżąco ze wszystkimi aktualizacjami Gato GraphQL.