Bài học 16: Gửi thông báo khi có bài viết mới
Gato GraphQL có thể giúp chúng ta tự động hóa các tác vụ trong ứng dụng, chẳng hạn như gửi email thông báo cho quản trị viên khi có bài viết mới.
Trong bài học hướng dẫn này, chúng ta sẽ khám phá hai cách để đạt được điều này.
GraphQL query để gửi email thông báo cho quản trị viên
GraphQL query này gửi một email đến người dùng quản trị viên, thông báo về việc tạo một bài viết mới trên trang:
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
}
}Để gửi email dưới dạng văn bản thuần túy:
- Sử dụng input
messageAs: { text: ... }trong mutation_sendEmail - Xóa các thẻ HTML khỏi nội dung bài viết bằng cách sử dụng global field
_htmlStripTags(được cung cấp bởi extension PHP Functions via Schema)
Tiếp theo, hãy xem cách kích hoạt việc thực thi GraphQL query.
Tùy chọn 1: Kích hoạt luôn luôn bằng cách phản ứng với các hook của WordPress
Chúng ta móc vào action WordPress core new_to_publish, lấy dữ liệu từ bài viết vừa được tạo, và thực thi GraphQL query đã định nghĩa ở trên đối với internal GraphQL server (được cung cấp thông qua extension Internal GraphQL Server):
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');
}
);Class GatoGraphQL\InternalGraphQLServer\GraphQLServer không thể truy cập như một API bên ngoài. Thay vào đó, nó được sử dụng bởi ứng dụng thông qua mã PHP, để thực thi/tự động hóa các tác vụ quản trị thông qua GraphQL queries.
Class này cung cấp 3 phương thức tĩnh để thực thi queries:
executeQuery: Thực thi một GraphQL queryexecuteQueryInFile: Thực thi một GraphQL query chứa trong một file (.gql)executePersistedQuery: Thực thi một persisted GraphQL query (cung cấp ID của nó dưới dạng int, hoặc slug dưới dạng string)
GraphQL query này sẽ được thực thi mỗi khi một bài viết mới được tạo, hay nói chính xác hơn, mỗi khi hàm WordPress wp_insert_post được gọi (vì hàm này kích hoạt hook new_to_publish):
$postID = wp_insert_post([
'post_title' => 'Hello world!'
]);Điều này cũng xảy ra khi thực thi một GraphQL query khác thực thi mutation createPost (vì resolver của nó, trong mã PHP, gọi hàm wp_insert_post):
mutation CreatePost {
createPost(input: {
title: "Hello world!"
}) {
status
postID
}
}GraphQL Server (là server "bên ngoài", được truy cập như một API qua HTTP) và Internal GraphQL Server sẽ thực thi các queries của mình áp dụng Schema Configuration riêng của từng server, ngay cả khi việc thực thi của chúng đan xen nhau.
Ví dụ, giả sử chúng ta đang thực thi một GraphQL query đối với single endpoint, và nó tạo một bài viết bằng cách thực thi mutation createPost. Khi đó, trình tự các bước sau sẽ diễn ra:
| (Bên ngoài) GraphQL Server | Internal GraphQL Server |
|---|---|
| Thực thi GraphQL query đối với single endpoint, sử dụng Schema Configuration của riêng nó | (không hoạt động) |
Tạo một bài viết; điều này kích hoạt new_to_publish | (không hoạt động) |
| (đang chờ...) | Phản ứng với hook new_to_publish: Khởi động Internal GraphQL server, sử dụng Schema Configuration của riêng nó |
| (đang chờ...) | Thực thi query để gửi email |
| (đang chờ...) | Gửi email, kết thúc query đó |
| (đang chờ...) | Tắt server |
| Tiếp tục thực thi query, kết thúc query đó | (không hoạt động) |
| Tắt server | (không hoạt động) |
Tùy chọn 2: Kích hoạt bằng cách xâu chuỗi các GraphQL queries
Extension Automation khiến GraphQL Server kích hoạt một hook sau khi hoàn thành việc thực thi một GraphQL query. Điều này cho phép chúng ta xâu chuỗi các GraphQL queries.
Mã PHP này thực thi operation SendEmail (GraphQL query đã định nghĩa ở trên), sau khi GraphQL server đã thực thi một query khác với operation CreatePost (GraphQL query đã định nghĩa ở trên):
// 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');
}
);Xâu chuỗi các GraphQL queries cho phép chúng ta chỉ thực thi một query duy nhất, ngay cả khi nhiều tài nguyên đã được thay đổi.
Ví dụ, GraphQL query này cập nhật nhiều bài viết:
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
}
}
}Tùy thuộc vào chiến lược của chúng ta, chúng ta có thể kích hoạt việc thực thi một hoặc nhiều GraphQL queries bổ sung:
| Móc vào... | Số GraphQL queries được kích hoạt... |
|---|---|
post_updated (bởi WordPress core) | Một cho mỗi bài viết được cập nhật |
gatographql__executed_query:ReplaceDomains (bởi extension Automation) | Một tổng cộng (sẽ nhận dữ liệu của tất cả các bài viết được cập nhật) |