GraphQL API와의 상호작용
GraphQL API와의 상호작용WordPress 없이 Gato GraphQL 실행하기

WordPress 없이 Gato GraphQL 실행하기

Gato GraphQL은 Composer로 관리되는 독립 실행형 PHP 컴포넌트를 사용하여 구축되었으며, GraphQL 서버를 구성하는 모든 PHP 컴포넌트가 WordPress에 의존하지 않도록 설계되었습니다.

따라서 GraphQL 서버는 독립 실행형 PHP 애플리케이션으로 실행할 수 있으며, WordPress 기반 애플리케이션이든 다른 무엇이든 임의의 PHP 애플리케이션에 포함시킬 수 있습니다.

특정 사용 사례에서 애플리케이션이 WordPress 데이터에 접근할 필요가 없다면, 적어도 그 사용 사례에서는 바로 사용할 수 있습니다.

이 동영상은 그러한 사용 사례를 시연합니다. 즉, GitHub API와 연동하여 개발 중에 GitHub Actions에서 아티팩트를 다운로드·설치하는 예입니다:

WordPress 없는 헤드리스 WordPress 데모: GraphQL 쿼리 실행

이 동영상에서 GraphQL 쿼리는 HTTP 요청을 실행하여 GitHub Actions에서 생성된 최신 Gato GraphQL 플러그인을 가져옵니다. 이 플러그인들은 풀 리퀘스트를 병합할 때 아티팩트로 업로드됩니다.

GraphQL 응답에서 얻은 아티팩트 URL은 WP-CLI에 주입되어, 로컬 DEV 웹 서버에 플러그인을 자동으로 설치하고 테스트를 실행합니다.

이 사용 사례에서는 WordPress 데이터에 전혀 접근하지 않으므로, GraphQL 서버는 이미 독립 실행형 PHP 앱으로 실행할 수 있습니다.

상세 설명: Gato GraphQL을 독립 실행형 PHP 앱으로 실행하기

여기서는 데모 동영상의 상세한 설명을 제공합니다.

실행할 GraphQL 쿼리는 파일 retrieve-github-artifacts.gql에 작성합니다.

이 쿼리는 환경 변수 GITHUB_ACCESS_TOKEN에서 액세스 토큰을 가져와 GitHub API에 연결합니다. 제공된 변수를 기반으로 actions/artifacts 엔드포인트의 전체 경로를 동적으로 생성한 후 해당 경로에 HTTP 요청을 보냅니다.

응답에서 각 아티팩트 항목 내의 「다운로드 URL」을 추출하여 비동기 HTTP 요청을 보냅니다. 각 「다운로드 URL」의 Location 헤더에서 다운로드 가능한 파일의 실제 URL을 가져옵니다.

마지막으로, WP-CLI에 주입하기 편리하도록 모든 URL을 공백으로 구분하여 함께 출력합니다.

# 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: " "
  )
}

PHP 로직은 Gato GraphQL 플러그인과 「Power Extensions」 번들(HTTP 요청 전송 및 기타 기능에 필요)의 코드를 직접 로드합니다.

독립 실행형 PHP 앱으로서, 어떤 모듈을 초기화할지 명시적으로 지정하고 기본값 이외의 설정을 제공해야 합니다.

예를 들어, 모듈 SendHTTPRequests에 대해 https://api.github.com/repos에의 연결을 허용하고, 모듈 EnvironmentFields에 대해 환경 변수 GITHUB_ACCESS_TOKEN에의 접근을 허용하도록 설정합니다.

GraphQL 스키마는 GraphQL 쿼리가 처음 실행될 때 생성되어 디스크에 캐시됩니다. 이로 인해 2번째 실행부터는 스키마를 계산하기 위한 코드가 전혀 실행되지 않아 실행 속도가 빨라집니다.

마지막으로, 독립 실행형 앱이 GraphQL 서버를 초기화하고, 쿼리를 실행하며, 응답을 출력합니다.

<?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 쿼리를 실행하려면 터미널에서 다음 명령을 실행합니다(jq를 사용하여 JSON을 보기 좋게 출력):

php retrieve-github-artifacts.php | jq

마지막으로, GraphQL 응답에서 아티팩트 URL을 추출하여 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