第16课:有新文章时发送通知
Gato GraphQL 可以帮助我们自动化应用程序中的任务,例如在有新文章时向管理员发送通知邮件。
在本教程课程中,我们将探讨实现这一目标的两种方式。
向管理员发送通知邮件的 GraphQL Query
以下 GraphQL query 向管理员用户发送一封邮件,通知其站点上有新文章被创建:
query GetEmailData(
$postTitle: String!,
$postContent: String!
$postURL: URL!
) {
adminEmail: optionValue(name: "admin_email")
@export(as: "adminEmail")
emailMessageTemplate: _strConvertMarkdownToHTML(
text: """
There is a [new post on the site]({$postURL}):
**{$postTitle}**:
{$postContent}
"""
)
emailMessage: _strReplaceMultiple(
search: ["{$postTitle}", "{$postContent}", "{$postURL}"],
replaceWith: [$postTitle, $postContent, $postURL],
in: $__emailMessageTemplate
)
@export(as: "emailMessage")
emailSubject: _sprintf(
string: "New post: \"%s\"",
values: [$postTitle]
)
@export(as: "emailSubject")
}
mutation SendEmail @depends(on: "GetEmailData") {
_sendEmail(
input: {
to: $adminEmail
subject: $emailSubject
messageAs: {
html: $emailMessage
}
}
) {
status
}
}以纯文本格式发送邮件:
- 在
_sendEmailmutation 中使用输入messageAs: { text: ... } - 使用 PHP Functions via Schema 扩展提供的全局字段
_htmlStripTags从文章内容中去除 HTML 标签
接下来,我们来看如何触发 GraphQL query 的执行。
选项 1:通过响应 WordPress 钩子始终触发
我们挂载到 WordPress 核心操作 new_to_publish,从新创建的文章中获取数据,并针对内部 GraphQL 服务器(由 Internal GraphQL Server 扩展提供)执行上面定义的 GraphQL query:
use GatoGraphQL\InternalGraphQLServer\GraphQLServer;
use WP_Post;
// The GraphQL query, under var `$query`, is the one defined above
// $query = '...';
add_action(
'new_to_publish',
function (WP_Post $post) use ($query) {
$variables = [
'postTitle' => $post->post_title,
'postContent' => $post->post_content,
'postURL' => get_permalink($post->ID),
]
GraphQLServer::executeQuery($query, $variables, 'SendEmail');
}
);类 GatoGraphQL\InternalGraphQLServer\GraphQLServer 不可作为外部 API 访问。它应由应用程序通过 PHP 代码调用,用于通过 GraphQL query 执行和自动化管理任务。
该类提供 3 个静态方法来执行 query:
executeQuery:执行一个 GraphQL queryexecuteQueryInFile:执行包含在(.gql)文件中的 GraphQL queryexecutePersistedQuery:执行一个持久化 GraphQL query(以 int 形式提供其 ID,或以 string 形式提供其 slug)
每当有新文章被创建时,此 GraphQL query 就会被执行。更准确地说,每当 WordPress 函数 wp_insert_post 被调用时就会执行(因为该函数会触发钩子 new_to_publish):
$postID = wp_insert_post([
'post_title' => 'Hello world!'
]);当执行另一个包含 createPost mutation 的 GraphQL query 时也是如此(因为其解析器在 PHP 代码中会调用函数 wp_insert_post):
mutation CreatePost {
createPost(input: {
title: "Hello world!"
}) {
status
postID
}
}GraphQL 服务器("外部"服务器,通过 HTTP 作为 API 访问)和 Internal GraphQL 服务器在执行 query 时各自应用自己的 Schema Configuration,即使两者的执行交织在一起也是如此。
例如,假设我们正在针对单一端点执行一个 GraphQL query,它通过执行 mutation createPost 来创建一篇文章。此时会发生以下一系列步骤:
| (外部) GraphQL Server | Internal GraphQL Server |
|---|---|
| 针对单一端点执行 GraphQL query,使用自己的 Schema Configuration | (未激活) |
创建文章,触发 new_to_publish | (未激活) |
| (等待中...) | 响应 new_to_publish 钩子:启动 Internal GraphQL 服务器,使用自己的 Schema Configuration |
| (等待中...) | 执行发送邮件的 query |
| (等待中...) | 发送邮件,该 query 结束 |
| (等待中...) | 关闭服务器 |
| 继续执行 query,该 query 结束 | (未激活) |
| 关闭服务器 | (未激活) |
选项 2:通过链式 GraphQL Query 触发
Automation 扩展使 GraphQL 服务器在完成一个 GraphQL query 的执行后触发一个钩子。这使我们能够链式执行 GraphQL query。
以下 PHP 代码在 GraphQL 服务器执行完带有 CreatePost 操作的某个 query(上面定义的 GraphQL query)之后,执行 SendEmail 操作(上面定义的 GraphQL query):
// The GraphQL query, under var `$query`, is the one defined above
// $query = '...';
add_action(
"gatographql__executed_query:CreatePost",
function (Response $response) use ($query) {
// @var string
$responseContent = $response->getContent();
// @var array<string,mixed>
$responseJSON = json_decode($responseContent, true);
$postID = $responseJSON['data']['createPost']['postID'] ?? null;
if ($postID === null) {
// Do nothing
return;
}
$post = get_post($postID);
$variables = [
'postTitle' => $post->post_title,
'postContent' => $post->post_content,
'postURL' => get_permalink($post->ID),
]
GraphQLServer::executeQuery($query, $variables, 'SendEmail');
}
);通过链式执行 GraphQL query,即使有许多资源被 mutation,我们也只需执行一个 query。
例如,以下 GraphQL query 更新了许多文章:
mutation ReplaceDomains {
posts {
id
rawContent
adaptedRawContent: _strReplace(
search: "https://my-old-domain.com"
replaceWith: "https://my-new-domain.com"
in: $__rawContent
)
update(input: {
contentAs: { html: $__adaptedRawContent }
}) {
status
postID
}
}
}根据我们的策略,我们可以触发一个或多个额外 GraphQL query 的执行:
| 挂载到... | 触发的 GraphQL Query 数量... |
|---|---|
post_updated(由 WordPress 核心触发) | 每个被更新的文章触发一次 |
gatographql__executed_query:ReplaceDomains(由 Automation 扩展触发) | 总计一次(将接收所有被更新文章的数据) |