Usando código DRY para renderizar bloques en el servidor (PHP) y el cliente (JS)
Los bloques dinámicos (Gutenberg) son bloques que construyen su estructura y contenido sobre la marcha cuando el bloque se renderiza en el front-end.
Renderizar un bloque dinámico en el front-end (para mostrarlo en el editor de WordPress) y en el lado del servidor (para generar el HTML para la entrada del blog) normalmente obtendrá sus datos de dos formas distintas:
- Conectándose a la API en el lado del cliente (JavaScript)
- Llamando a funciones de WordPress en el lado del servidor (PHP)
Con Gato GraphQL y sus extensiones, es posible hacer esta lógica DRY, teniendo una única fuente de verdad para obtener datos tanto para el cliente como para el servidor. Vamos a explorar cómo hacerlo.
Almacenando consultas GraphQL en archivos .gql
Para conectarnos al servidor GraphQL desde el cliente, normalmente ejecutamos la consulta GraphQL embebida dentro del código JavaScript, así:
const response = await fetch(endpoint, {
body: JSON.stringify({
query: `
query {
posts {
id
title
author {
id
name
}
}
}
`
)
} );Alternativamente, podemos almacenar la consulta GraphQL en un archivo .gql (o .graphql), e importar su contenido usando raw-loader de Webpack:
// 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;(Este código funciona para Webpack v4; para v5, debemos usar Asset Modules en su lugar.)
A continuación, colocamos la consulta GraphQL dentro de un archivo .gql:
# File graphql-documents/fetch-posts-with-author.gql
query {
posts {
id
title
author {
id
name
}
}
}Finalmente, dentro del código del bloque, importamos el archivo y pasamos su contenido a fetch:
import graphQLQuery from './graphql-documents/fetch-posts-with-author.gql';
// ...
const response = await fetch(endpoint, {
body: JSON.stringify({
query: graphQLQuery
)
} );Resolviendo archivos .gql en el lado del servidor
El archivo GraphQL que creamos arriba será nuestra única fuente de verdad para obtener datos para el bloque. Ya satisface esto para el lado del cliente; ahora veamos cómo hacerlo para el lado del servidor.
La extensión Internal GraphQL Server instala un servidor que puede invocarse dentro de nuestra aplicación, usando código PHP.
el Internal GraphQL Server proporciona los siguientes métodos estáticos, vía la clase GraphQLServer:
executeQuery: ejecuta una consulta GraphQLexecuteQueryInFile: ejecuta una consulta GraphQL contenida en un archivo (.gql)executePersistedQuery: ejecuta una consulta GraphQL persistida (proporcionando su ID como int, o slug como string) (se requiere la extensión Persisted Queries)
La firma de executeQueryInFile tiene este aspecto:
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 {
// ...
}
}Invocando executeQueryInFile pasando el archivo .gql creado anteriormente, recuperamos los datos al renderizar el bloque dinámico:
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);De este modo, un único archivo .gql recupera los datos para alimentar bloques tanto en el lado del cliente como en el del servidor.