Coderen met een API
Coderen met een APIDRY-code gebruiken om blokken te renderen voor de server (PHP) en client (JS)

DRY-code gebruiken om blokken te renderen voor de server (PHP) en client (JS)

Dynamische (Gutenberg) blokken zijn blokken die hun structuur en inhoud dynamisch opbouwen op het moment dat het blok wordt gerenderd op de front-end.

Het renderen van een dynamisch blok op de front-end (om het weer te geven in de WordPress-editor) en aan de serverkant (om de HTML voor de blogpost te genereren) haalt de data doorgaans op twee verschillende manieren op:

  • Door verbinding te maken met de API aan de clientkant (JavaScript)
  • Door WordPress-functies aan te roepen aan de serverkant (PHP)

Met Gato GraphQL en extensies is het mogelijk om deze logica DRY te maken, met één enkele bron van waarheid om data op te halen voor zowel de client- als de serverkant. Laten we bekijken hoe je dit doet.

GraphQL queries opslaan in .gql-bestanden

Om verbinding te maken met de GraphQL-server vanuit de client, voeren we de GraphQL query doorgaans uit als onderdeel van de JavaScript-code, als volgt:

const response = await fetch(endpoint, {
  body: JSON.stringify({
    query: `
      query {
        posts {
          id
          title
          author {
            id
            name
          }
        }
      }
    `
  )
} );

We kunnen de GraphQL query ook opslaan in een .gql- (of .graphql-)bestand en de inhoud importeren via Webpack's raw-loader:

// File webpack.config.js
const config = require( '@wordpress/scripts/config/webpack.config' );
 
config.module.rules.push(
  {
    test: /\.(gql|graphql)$/i,
    use: 'raw-loader',
  },
);
 
module.exports = config;

(Deze code werkt voor Webpack v4; voor v5 moet je in plaats daarvan Asset Modules gebruiken.)

Vervolgens plaatsen we de GraphQL query in een .gql-bestand:

# File graphql-documents/fetch-posts-with-author.gql
query {
  posts {
    id
    title
    author {
      id
      name
    }
  }
}

Ten slotte importeren we in de code van het blok het bestand en geven we de inhoud door aan fetch:

import graphQLQuery from './graphql-documents/fetch-posts-with-author.gql';
 
// ...
 
const response = await fetch(endpoint, {
  body: JSON.stringify({
    query: graphQLQuery
  )
} );

.gql-bestanden verwerken aan de serverkant

Het GraphQL-bestand dat we hierboven hebben aangemaakt, wordt onze enige bron van waarheid om data voor het blok op te halen. Het voldoet al aan deze vereiste voor de clientkant; laten we nu bekijken hoe we hetzelfde voor de serverkant doen.

De extensie Internal GraphQL Server installeert een server die binnen onze applicatie kan worden aangeroepen via PHP-code.

De Internal GraphQL Server biedt de volgende statische methoden via de klasse GraphQLServer:

  • executeQuery: Voert een GraphQL query uit
  • executeQueryInFile: Voert een GraphQL query uit die is opgeslagen in een (.gql-)bestand
  • executePersistedQuery: Voert een bewaarde GraphQL query uit (door het ID als integer of de slug als string op te geven) (de extensie Persisted Queries is vereist)

De signatuur van executeQueryInFile ziet er als volgt uit:

namespace GatoGraphQL\InternalGraphQLServer;
 
class GraphQLServer {
  /**
   * Execute a GraphQL query contained in a (`.gql`) file
   */
  public static function executeQueryInFile(
      string $file,
      array $variables = [],
      ?string $operationName = null
  ): Response {
    // ...
  }
}

Door executeQueryInFile aan te roepen met het eerder aangemaakte .gql-bestand, halen we de data op bij het renderen van het dynamische blok:

use GatoGraphQL\InternalGraphQLServer\GraphQLServer;
 
$block = [
  'render_callback' => function(array $attributes, string $content): string {
    // Provide the GraphQL query file
    $file = __DIR__ . '/blocks/my-block/graphql-documents/fetch-posts-with-author.gql';
 
    // Execute the query against the internal server
    $response = GraphQLServer::executeQueryInFile($file);
 
    // Get the content and decode it
    $responseContent = json_decode($response->getContent(), true);
 
    // Access the data and errors from the response
    $data = $responseContent["data"] ?? [];
    $errors = $responseContent["errors"] ?? [];
 
    // Do something with the data
    // $content = $this->useGraphQLData($content, $data, $errors);
    // ...
 
    return $content;
  },
];
register_block_type("namespace/my-block", $block);

Op deze manier haalt één enkel .gql-bestand de data op die blokken van stroom voorziet, zowel aan de client- als de serverkant.