通过 API 编写代码使用 DRY 代码为服务器端(PHP)和客户端(JS)渲染块
使用 DRY 代码为服务器端(PHP)和客户端(JS)渲染块
动态(Gutenberg)块是指在前端渲染块时动态构建其结构和内容的块。
在前端(显示于 WordPress 编辑器)和服务器端(为博客文章生成 HTML)渲染动态块时,通常以两种不同的方式获取数据:
- 在客户端(JavaScript)连接 API
- 在服务器端(PHP)调用 WordPress 函数
借助 Gato GraphQL 及其扩展,可以将此逻辑变为 DRY,为客户端和服务器端的数据获取提供单一可信来源。下面来看如何实现。
将 GraphQL queries 存储在 .gql 文件中
要从客户端连接到 GraphQL 服务器,通常将 GraphQL query 嵌入 JavaScript 代码中执行,例如:
const response = await fetch(endpoint, {
body: JSON.stringify({
query: `
query {
posts {
id
title
author {
id
name
}
}
}
`
)
} );也可以将 GraphQL query 存储在 .gql(或 .graphql)文件中,并使用 Webpack 的 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;(此代码适用于 Webpack v4;对于 v5,必须改用 Asset Modules。)
接下来,将 GraphQL query 放入 .gql 文件中:
# File graphql-documents/fetch-posts-with-author.gql
query {
posts {
id
title
author {
id
name
}
}
}最后,在块的代码中导入该文件并将其内容传递给 fetch:
import graphQLQuery from './graphql-documents/fetch-posts-with-author.gql';
// ...
const response = await fetch(endpoint, {
body: JSON.stringify({
query: graphQLQuery
)
} );在服务器端解析 .gql 文件
上面创建的 GraphQL 文件将成为获取块数据的单一可信来源。客户端已经满足需求;现在来看服务器端如何实现。
Internal GraphQL Server 扩展会安装一个可在应用程序内通过 PHP 代码调用的服务器。
Internal GraphQL Server 通过 GraphQLServer 类提供以下静态方法:
executeQuery:执行一个 GraphQL queryexecuteQueryInFile:执行包含在(.gql)文件中的 GraphQL queryexecutePersistedQuery:执行一个持久化的 GraphQL query(以 int 提供其 ID,或以 string 提供其 slug)(需要 Persisted Queries 扩展)
executeQueryInFile 的签名如下:
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 {
// ...
}
}通过传入之前创建的 .gql 文件来调用 executeQueryInFile,即可在渲染动态块时获取数据:
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);这样,单个 .gql 文件便可同时为客户端和服务器端的块提供数据。
Prev
Next