Chạy Gato GraphQL không có WordPress
Gato GraphQL được xây dựng bằng các thành phần PHP độc lập, được quản lý qua Composer, theo cách mà tất cả các thành phần PHP tạo nên máy chủ GraphQL đều không phụ thuộc vào WordPress!
Do đó, máy chủ GraphQL có thể chạy như một ứng dụng PHP độc lập, và bạn có thể tích hợp nó vào bất kỳ ứng dụng PHP nào, dựa trên WordPress hay bất cứ nền tảng nào khác.
Nếu trong một số trường hợp sử dụng, ứng dụng của bạn không cần truy cập dữ liệu WordPress, thì ít nhất với những trường hợp đó, bạn đã sẵn sàng.
Video này minh họa một trường hợp sử dụng như vậy: Tương tác với API của GitHub, để tải xuống/cài đặt các artifact từ GitHub Actions trong quá trình phát triển:
Trong video, GraphQL query thực hiện một yêu cầu HTTP để lấy các plugin Gato GraphQL mới nhất được tạo trong GitHub Actions, được tải lên dưới dạng artifact khi merge một pull request.
Các URL của artifact từ phản hồi GraphQL sau đó được đưa vào WP-CLI, để các plugin được cài đặt tự động trên máy chủ web DEV cục bộ, nhằm chạy các bài kiểm tra.
Trong trường hợp sử dụng này, vì không có dữ liệu WordPress nào được truy cập, máy chủ GraphQL đã có thể chạy như một ứng dụng PHP độc lập.
Chi tiết: Chạy Gato GraphQL như một ứng dụng PHP độc lập
Dưới đây là giải thích chi tiết về video demo.
Chúng ta cung cấp GraphQL query để chạy trong file retrieve-github-artifacts.gql.
Query kết nối với API GitHub bằng cách lấy access token từ biến môi trường GITHUB_ACCESS_TOKEN. Nó tự động tạo đường dẫn đầy đủ cho endpoint actions/artifacts từ các biến được cung cấp, rồi gửi một yêu cầu HTTP tới endpoint đó.
Từ phản hồi, nó trích xuất "download URL" từ trong từng artifact item, và gửi các yêu cầu HTTP bất đồng bộ tới chúng. Từ header Location của mỗi "download URL" này, chúng ta lấy được URL thực tế của file có thể tải xuống.
Cuối cùng, nó in tất cả các URL cùng nhau được phân tách bằng dấu cách, để tiện đưa vào WP-CLI.
# File retrieve-github-artifacts.gql
query RetrieveProxyArtifactDownloadURLs(
$repoOwner: String!
$repoProject: String!
$perPage: Int = 1
$artifactName: String = ""
) {
githubAccessToken: _env(name: "GITHUB_ACCESS_TOKEN")
@remove
# Create the authorization header to send to GitHub
authorizationHeader: _sprintf(
string: "Bearer %s"
values: [$__githubAccessToken]
)
@remove
# Create the authorization header to send to GitHub
githubRequestHeaders: _echo(
value: [
{ name: "Accept", value: "application/vnd.github+json" }
{ name: "Authorization", value: $__authorizationHeader }
]
)
@remove
@export(as: "githubRequestHeaders")
githubAPIEndpoint: _sprintf(
string: "https://api.github.com/repos/%s/%s/actions/artifacts?per_page=%s&name=%s"
values: [$repoOwner, $repoProject, $perPage, $artifactName]
)
# Use the field from "Send HTTP Request Fields" to connect to GitHub
gitHubArtifactData: _sendJSONObjectItemHTTPRequest(
input: {
url: $__githubAPIEndpoint
options: { headers: $__githubRequestHeaders }
}
)
@remove
# Finally just extract the URL from within each "artifacts" item
gitHubProxyArtifactDownloadURLs: _objectProperty(
object: $__gitHubArtifactData
by: { key: "artifacts" }
)
@underEachArrayItem(passValueOnwardsAs: "artifactItem")
@applyField(
name: "_objectProperty"
arguments: { object: $artifactItem, by: { key: "archive_download_url" } }
setResultInResponse: true
)
@export(as: "gitHubProxyArtifactDownloadURLs")
}
query CreateHTTPRequestInputs
@depends(on: "RetrieveProxyArtifactDownloadURLs")
{
httpRequestInputs: _echo(value: $gitHubProxyArtifactDownloadURLs)
@underEachArrayItem(passValueOnwardsAs: "url")
@applyField(
name: "_objectAddEntry"
arguments: {
object: {
options: { headers: $githubRequestHeaders, allowRedirects: null }
}
key: "url"
value: $url
}
setResultInResponse: true
)
@export(as: "httpRequestInputs")
@remove
}
query RetrieveActualArtifactDownloadURLs
@depends(on: "CreateHTTPRequestInputs")
{
_sendHTTPRequests(inputs: $httpRequestInputs) {
artifactDownloadURL: header(name: "Location")
@export(as: "artifactDownloadURLs", type: LIST)
}
}
query PrintSpaceSeparatedArtifactDownloadURLs
@depends(on: "RetrieveActualArtifactDownloadURLs")
{
spaceSeparatedArtifactDownloadURLs: _arrayJoin(
array: $artifactDownloadURLs
separator: " "
)
}Logic PHP tải trực tiếp code từ plugin Gato GraphQL và từ bundle "Power Extensions" (cần thiết để gửi các yêu cầu HTTP và các chức năng khác).
Là một ứng dụng PHP độc lập, chúng ta phải chỉ định rõ ràng những module nào được khởi tạo và cung cấp mọi cấu hình không mặc định.
Ví dụ, chúng ta yêu cầu module SendHTTPRequests cho phép kết nối tới https://api.github.com/repos, và module EnvironmentFields cho phép truy cập biến môi trường GITHUB_ACCESS_TOKEN.
Lưu ý rằng schema GraphQL được tạo lần đầu tiên khi GraphQL query được thực thi, và được lưu vào cache trên đĩa. Theo cách này, từ lần thứ 2 trở đi, không có code nào để tính toán schema được thực thi, giúp việc thực thi nhanh hơn.
Cuối cùng, ứng dụng độc lập khởi tạo máy chủ GraphQL, thực thi query trên đó và in ra phản hồi.
<?php
// File retrieve-github-artifacts.php
declare(strict_types=1);
use GraphQLByPoP\GraphQLServer\Server\StandaloneGraphQLServer;
use PoP\Root\Container\ContainerCacheConfiguration;
// Load the GraphQL server via the standalone PHP components
require_once (__DIR__ . '/wordpress/wp-content/plugins/gatographql/vendor/scoper-autoload.php');
// Load the PRO extensions via the standalone PHP components
require_once (__DIR__ . '/wordpress/wp-content/plugins/gatographql-power-extensions-bundle/vendor/scoper-autoload.php');
// Modules required in the GraphQL query
$moduleClasses = [
\PoPSchema\EnvironmentFields\Module::class,
\PoPSchema\FunctionFields\Module::class,
\GraphQLByPoP\ExportDirective\Module::class,
\GraphQLByPoP\DependsOnOperationsDirective\Module::class,
\GraphQLByPoP\RemoveDirective\Module::class,
\PoPSchema\ApplyFieldDirective\Module::class,
\PoPSchema\SendHTTPRequests\Module::class,
\PoPSchema\ConditionalMetaDirectives\Module::class,
\PoPSchema\DataIterationMetaDirectives\Module::class,
];
// Configure the modules
$moduleClassConfiguration = [
\PoP\GraphQLParser\Module::class => [
\PoP\GraphQLParser\Environment::ENABLE_MULTIPLE_QUERY_EXECUTION => true,
\PoP\GraphQLParser\Environment::USE_LAST_OPERATION_IN_DOCUMENT_FOR_MULTIPLE_QUERY_EXECUTION_WHEN_OPERATION_NAME_NOT_PROVIDED => true,
\PoP\GraphQLParser\Environment::ENABLE_RESOLVED_FIELD_VARIABLE_REFERENCES => true,
\PoP\GraphQLParser\Environment::ENABLE_COMPOSABLE_DIRECTIVES => true,
],
\PoPSchema\SendHTTPRequests\Module::class => [
\PoPSchema\SendHTTPRequests\Environment::SEND_HTTP_REQUEST_URL_ENTRIES => [
'#https://api.github.com/repos/(.*)#',
],
],
\PoPSchema\EnvironmentFields\Module::class => [
\PoPSchema\EnvironmentFields\Environment::ENVIRONMENT_VARIABLE_OR_PHP_CONSTANT_ENTRIES => [
'GITHUB_ACCESS_TOKEN',
],
],
];
// Cache the schema to disk, to speed-up execution from the 2nd time onwards
$containerCacheConfiguration = new ContainerCacheConfiguration('MyGraphQLServer', true, 'retrieve-github-artifacts', __DIR__ . '/tmp');
// Initialize the server
$graphQLServer = new StandaloneGraphQLServer($moduleClasses, $moduleClassConfiguration, [], [], $containerCacheConfiguration);
/**
* GraphQL query to execute, stored in its own .gql file
*
* @var string
*/
$query = file_get_contents(__DIR__ . '/retrieve-github-artifacts.gql');
// GraphQL variables
$variables = [
'repoOwner' => 'GatoGraphQL',
'repoProject' => 'GatoGraphQL',
'perPage' => 3
];
// Execute the query
$response = $graphQLServer->execute(
$query,
$variables,
);
// Print the response
echo $response->getContent();Để thực thi GraphQL query, chúng ta chạy trong terminal (sử dụng jq để in đẹp JSON output):
php retrieve-github-artifacts.php | jqCuối cùng, để trích xuất các artifact URL từ phản hồi GraphQL và đưa chúng vào WP-CLI, chúng ta chạy:
GITHUB_ARTIFACT_URLS=$(php retrieve-github-artifacts.php \
| grep -E -o '"spaceSeparatedArtifactDownloadURLs\":"(.*)"' \
| cut -d':' -f2- | cut -d'"' -f2- | rev | cut -d'"' -f2- | rev \
| sed 's/\\\//\//g')
wp plugin install ${GITHUB_ARTIFACT_URLS} --force --activate