DRY-Code zum Rendern von Blöcken für Server (PHP) und Client (JS)
Dynamische (Gutenberg-)Blöcke sind Blöcke, die ihre Struktur und ihren Inhalt dynamisch aufbauen, wenn der Block im Frontend gerendert wird.
Beim Rendern eines dynamischen Blocks im Frontend (zur Anzeige im WordPress-Editor) und serverseitig (zur Generierung des HTML für den Blogbeitrag) werden die Daten typischerweise auf zwei unterschiedliche Arten abgerufen:
- Verbindung zur API auf der Clientseite (JavaScript)
- Aufruf von WordPress-Funktionen auf der Serverseite (PHP)
Mit Gato GraphQL und seinen Erweiterungen ist es möglich, diese Logik DRY zu gestalten und eine einzige Quelle der Wahrheit zu haben, um Daten sowohl client- als auch serverseitig abzurufen. Schauen wir uns an, wie das geht.
GraphQL-queries in .gql-Dateien speichern
Um vom Client aus eine Verbindung zum GraphQL-Server herzustellen, führen wir die GraphQL-query typischerweise direkt im JavaScript-Code eingebettet aus, etwa so:
const response = await fetch(endpoint, {
body: JSON.stringify({
query: `
query {
posts {
id
title
author {
id
name
}
}
}
`
)
} );Alternativ können wir die GraphQL-query in einer .gql- (oder .graphql-)Datei speichern und deren Inhalt mit Webpacks raw-loader importieren:
// 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;(Dieser Code funktioniert für Webpack v4; für v5 müssen stattdessen Asset Modules verwendet werden.)
Als Nächstes platzieren wir die GraphQL-query in einer .gql-Datei:
# File graphql-documents/fetch-posts-with-author.gql
query {
posts {
id
title
author {
id
name
}
}
}Schließlich importieren wir die Datei im Code des Blocks und übergeben ihren Inhalt an fetch:
import graphQLQuery from './graphql-documents/fetch-posts-with-author.gql';
// ...
const response = await fetch(endpoint, {
body: JSON.stringify({
query: graphQLQuery
)
} );.gql-Dateien serverseitig auflösen
Die oben erstellte GraphQL-Datei wird unsere einzige Quelle der Wahrheit für den Datenabruf des Blocks sein. Für die Clientseite ist das bereits erfüllt; schauen wir nun, wie es für die Serverseite funktioniert.
Die Erweiterung Internal GraphQL Server installiert einen Server, der innerhalb unserer Anwendung per PHP-Code aufgerufen werden kann.
der Internal GraphQL Server stellt die folgenden statischen Methoden über die Klasse GraphQLServer bereit:
executeQuery: führt eine GraphQL-query ausexecuteQueryInFile: führt eine GraphQL-query aus, die in einer (.gql-)Datei enthalten istexecutePersistedQuery: führt eine persistierte GraphQL-query aus (unter Angabe ihrer ID als Integer oder ihres Slugs als String) (die Erweiterung Persisted Queries ist erforderlich)
Die Signatur von executeQueryInFile sieht wie folgt aus:
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 {
// ...
}
}Indem wir executeQueryInFile mit der zuvor erstellten .gql-Datei aufrufen, rufen wir die Daten beim Rendern des dynamischen Blocks ab:
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);Auf diese Weise ruft eine einzige .gql-Datei die Daten ab, um Blöcke sowohl client- als auch serverseitig zu betreiben.