Berinteraksi dengan API GraphQL
Berinteraksi dengan API GraphQLMenjalankan Gato GraphQL tanpa WordPress

Menjalankan Gato GraphQL tanpa WordPress

Gato GraphQL dibangun menggunakan komponen PHP mandiri yang dikelola melalui Composer, sedemikian rupa sehingga semua komponen PHP yang membentuk server GraphQL tidak bergantung pada WordPress!

Oleh karena itu, server GraphQL dapat dijalankan sebagai aplikasi PHP mandiri, dan Anda dapat menyertakannya dalam aplikasi PHP apa pun, baik yang berbasis WordPress maupun yang lain.

Jika untuk suatu kasus penggunaan aplikasi Anda tidak perlu mengakses data WordPress, maka, setidaknya untuk kasus penggunaan tersebut, Anda sudah siap untuk memulai.

Video ini mendemonstrasikan kasus penggunaan seperti itu: berinteraksi dengan API GitHub, untuk mengunduh/menginstal artefak dari GitHub Actions selama pengembangan:

Demo Headless WordPress tanpa WordPress: Menjalankan GraphQL query

Dalam video tersebut, GraphQL query menjalankan permintaan HTTP untuk mengambil plugin Gato GraphQL terbaru yang dihasilkan di GitHub Actions, yang diunggah sebagai artefak saat melakukan merge pull request.

URL artefak dari respons GraphQL kemudian disuntikkan ke WP-CLI, agar plugin secara otomatis terinstal di server web DEV lokal untuk menjalankan pengujian.

Dalam kasus penggunaan ini, karena tidak ada data WordPress yang diakses sama sekali, server GraphQL sudah dapat dijalankan sebagai aplikasi PHP mandiri.

Secara Rinci: Menjalankan Gato GraphQL sebagai Aplikasi PHP Mandiri

Berikut penjelasan rinci dari video demo.

Kami menyediakan GraphQL query yang akan dijalankan dalam file retrieve-github-artifacts.gql.

Query tersebut terhubung ke API GitHub dengan mengambil access token dari variabel lingkungan GITHUB_ACCESS_TOKEN. Query ini secara dinamis menghasilkan jalur lengkap untuk endpoint actions/artifacts dari variabel yang diberikan, kemudian mengirimkan permintaan HTTP ke sana.

Dari respons tersebut, query mengekstrak "download URL" dari setiap item artefak, dan mengirimkan permintaan HTTP asinkron ke sana. Dari header Location masing-masing "download URL" tersebut, kami mendapatkan URL sebenarnya dari file yang dapat diunduh.

Terakhir, query mencetak semua URL bersama-sama yang dipisahkan oleh spasi, agar mudah disuntikkan ke 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: " "
  )
}

Logika PHP secara langsung memuat kode dari plugin Gato GraphQL, dan dari bundle "Power Extensions" (diperlukan untuk mengirimkan permintaan HTTP, dan fungsionalitas lainnya).

Sebagai aplikasi PHP mandiri, kita harus secara eksplisit menentukan modul apa yang diinisialisasi, dan menyediakan konfigurasi yang tidak menggunakan nilai default.

Sebagai contoh, kami memberi tahu modul SendHTTPRequests untuk mengizinkan koneksi ke https://api.github.com/repos, dan modul EnvironmentFields untuk mengizinkan akses ke variabel lingkungan GITHUB_ACCESS_TOKEN.

Perhatikan bahwa skema GraphQL dibuat pada pertama kali GraphQL query dijalankan, dan di-cache ke disk. Dengan cara ini, mulai dari eksekusi ke-2 dan seterusnya, tidak ada kode untuk menghitung skema yang dijalankan, sehingga eksekusi menjadi lebih cepat.

Terakhir, aplikasi mandiri menginisialisasi server GraphQL, menjalankan query terhadapnya, dan mencetak respons.

<?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();

Untuk menjalankan GraphQL query, kita jalankan di terminal (menggunakan jq untuk mencetak output JSON dengan format yang rapi):

php retrieve-github-artifacts.php | jq

Terakhir, untuk mengekstrak URL artefak dari respons GraphQL, dan menyuntikkannya ke WP-CLI, kita jalankan:

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