การรัน Gato GraphQL โดยไม่ต้องใช้ WordPress
Gato GraphQL ถูกสร้างขึ้นโดยใช้คอมโพเนนต์ PHP แบบ standalone ที่จัดการผ่าน Composer ในลักษณะที่ คอมโพเนนต์ PHP ทั้งหมดที่ประกอบเป็น GraphQL server ไม่ได้ขึ้นอยู่กับ WordPress!
ดังนั้น GraphQL server สามารถรันในฐานะแอปพลิเคชัน PHP แบบ standalone และคุณสามารถรวมมันไว้ในแอปพลิเคชัน PHP ใดก็ได้ ไม่ว่าจะเป็นแบบที่ใช้ WordPress หรืออย่างอื่น
หากสำหรับกรณีการใช้งานบางอย่าง แอปพลิเคชันของคุณไม่จำเป็นต้องเข้าถึงข้อมูล WordPress คุณก็พร้อมใช้งานได้เลยสำหรับกรณีนั้นอย่างน้อย
วิดีโอนี้แสดงให้เห็นกรณีการใช้งานดังกล่าว: การโต้ตอบกับ API ของ GitHub เพื่อดาวน์โหลด/ติดตั้ง artifacts จาก GitHub Actions ระหว่างการพัฒนา:
ในวิดีโอ GraphQL query จะรัน HTTP request เพื่อดึงข้อมูล Gato GraphQL plugins เวอร์ชันล่าสุดที่สร้างใน GitHub Actions ซึ่งถูกอัปโหลดเป็น artifacts เมื่อมีการ merge pull request
URL ของ artifacts จาก GraphQL response จะถูกนำไปใส่ใน WP-CLI เพื่อให้ plugins ถูกติดตั้งโดยอัตโนมัติใน DEV webserver ภายในเครื่อง เพื่อรัน tests
ในกรณีการใช้งานนี้ เนื่องจากไม่มีการเข้าถึงข้อมูล WordPress เลย GraphQL server จึงสามารถรันในฐานะแอป PHP แบบ standalone ได้แล้ว
รายละเอียด: การรัน Gato GraphQL ในฐานะแอป PHP แบบ Standalone
นี่คือคำอธิบายโดยละเอียดของวิดีโอสาธิต
เราระบุ GraphQL query ที่จะรันไว้ในไฟล์ retrieve-github-artifacts.gql
Query เชื่อมต่อกับ GitHub API โดยรับ access token จาก env var GITHUB_ACCESS_TOKEN มันสร้าง full path สำหรับ endpoint actions/artifacts แบบ dynamic จากตัวแปรที่ให้มา และส่ง HTTP request ไปยัง endpoint นั้น
จาก response จะดึง "download URL" จากภายในแต่ละ artifact item และส่ง HTTP request แบบ asynchronous ไปยัง URL เหล่านั้น จาก Location header ของแต่ละ "download URL" เหล่านี้ เราได้รับ URL จริงของไฟล์ที่ดาวน์โหลดได้
สุดท้าย มันพิมพ์ URL ทั้งหมดโดยคั่นด้วยช่องว่าง เพื่อความสะดวกในการนำไปใส่ใน 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 จะโหลดโค้ดโดยตรงจาก Gato GraphQL plugin และจาก "Power Extensions" bundle (ที่จำเป็นสำหรับการส่ง HTTP requests และฟังก์ชันการทำงานอื่น ๆ)
ในฐานะแอป PHP แบบ standalone เราต้องระบุอย่างชัดเจนว่า modules ใดที่จะถูก initialize และกำหนดค่าที่ไม่ใช่ค่าเริ่มต้น
ตัวอย่างเช่น เราบอกให้ module SendHTTPRequests อนุญาตการเชื่อมต่อไปยัง https://api.github.com/repos และบอกให้ module EnvironmentFields อนุญาตการเข้าถึง environment variable GITHUB_ACCESS_TOKEN
โปรดทราบว่า GraphQL schema จะถูกสร้างครั้งแรกเมื่อ GraphQL query ถูกรัน และถูก cache ไว้ที่ disk ด้วยวิธีนี้ ตั้งแต่ครั้งที่ 2 เป็นต้นไป โค้ดที่คำนวณ schema จะไม่ถูกรัน ทำให้การรันเร็วขึ้น
สุดท้าย แอป standalone จะ initialize GraphQL server รัน query ตาม server นั้น และพิมพ์ response
<?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();เพื่อรัน GraphQL query เราเรียกใช้ในเทอร์มินัล (โดยใช้ jq เพื่อแสดง JSON output แบบ pretty print):
php retrieve-github-artifacts.php | jqสุดท้าย เพื่อดึง artifact URL จาก GraphQL response และนำไปใส่ใน WP-CLI เราเรียกใช้:
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