서비스 API를 사용하는 WordPress 플러그인 만들기, "수프에서 견과류까지"
게시 됨: 2022-03-10점점 더 많은 수의 공개적으로 사용 가능한 API가 애플리케이션의 기능을 확장하는 강력한 서비스를 제공합니다. WordPress는 소규모 개인 블로그에서 주요 전자 상거래 웹 사이트 및 그 사이의 모든 것을 지원하는 믿을 수 없을 정도로 역동적이고 유연한 CMS입니다. WordPress를 다재다능하게 만드는 부분 중 하나는 강력한 플러그인 시스템 으로 기능을 추가하기가 매우 쉽습니다.
짧은 코드를 사용하여 WordPress 페이지에 GitHub API의 데이터를 표시할 수 있는 플러그인인 GitHub Pipeline을 만든 방법을 살펴보겠습니다. 구체적인 예와 코드 조각을 제공할 것이지만 플러그인과 함께 서비스 API를 사용하는 방법에 대한 청사진에 설명된 기술을 고려하십시오.
SmashingMag에 대한 추가 정보:
- WordPress Essentials: WordPress 플러그인을 만드는 방법
- Transients를 사용하여 GitHub로 WordPress 플러그인을 배포하는 방법
- 플러그인에 구성 가능한 필드를 추가하는 세 가지 접근 방식
처음부터 시작하지만 WordPress 및 플러그인 개발에 어느 정도 익숙하다고 가정하고 WordPress 또는 Composer 설치와 같은 초보자 주제에 시간을 할애하지 않습니다.
너는 필요할거야:
- WordPress를 새로 설치한 PHP 환경
- GitHub 계정(또는 즉석에서 수행하려는 경우 다른 API 제공자)
- 작곡가(권장).
API 선택
이러한 종류의 플러그인을 작성하는 첫 번째 단계는 API를 선택하는 것입니다. 이 자습서에서는 GitHub API를 사용합니다. 다른 API를 사용할 생각이라면 프로젝트의 보상에 영향을 줄 수 있는 몇 가지 중요한 요소를 고려하십시오.
내가 가장 먼저 살펴보는 것 중 하나는 API 문서의 철저함과 품질입니다. 희소하거나 구식인 경우 소스 코드를 살펴보고 자신의 질문에 답하는 데 시간을 할애할 준비를 하십시오. 또한 API가 얼마나 성숙하고 공급자가 API를 얼마나 책임감 있게 버전화했는지 고려하십시오. 훌륭한 것을 만드는 데 시간을 투자하는 것보다 더 나쁜 것은 없습니다. 다만 업스트림 API의 변경으로 인해 중단되기만 하면 됩니다. 끝점 URL에서 버전 관리 시스템을 찾습니다.
// good https://api.stable.com/v1/user/ // danger https://api.dodgy.com/user/
분명히 말할 위험이 있지만 타사 API에 대한 프로그래밍에는 신뢰 관계가 포함되며 모든 API가 동일하게 생성되는 것은 아닙니다.
도서관 쇼핑
기존 브랜드는 API 작업을 더 쉽게 하기 위해 라이브러리나 SDK를 배포하는 경우가 많습니다. 그렇지 않은 경우 다른 사람이 이미 라이브러리를 작성했는지 조사하고 바퀴를 재발명하기 전에 기억하십시오. Google과 GitHub는 연구를 시작하기에 좋은 두 곳입니다. GitHub의 별 또는 포크 수는 라이브러리가 얼마나 효과적인지 보여주는 좋은 지표입니다. 가장 최근 커밋의 기간 및/또는 미해결 문제의 수는 해당 커밋이 얼마나 적극적으로 유지 관리되는지를 나타냅니다. 제 경우에는 운 좋게 KNP Labs에서 멋진 PHP GitHub API를 찾았습니다.
Guzzle로 나만의 글쓰기
공급자를 위한 만족스러운 라이브러리가 없는 경우에도 Guzzle과 같은 도구를 사용하면 HTTP 요청을 훨씬 쉽게 처리할 수 있으므로 처음부터 시작해서는 안 됩니다. Guzzle은 PHP의 cURL 라이브러리를 래핑하고 일반적으로 수동으로 구성하고 요청하는 것과 관련된 많은 골칫거리를 제거합니다. 하나 또는 두 개의 요청만 하는 경우에도 코드를 더 강력하게 만들고 Composer와 함께 설치하는 것은 케이크 조각이기 때문에 여전히 사용하는 것이 좋습니다.
플러그인 설정
두 개의 파일이 있는 디렉토리인 최소 WordPress 플러그인의 기본 골격부터 시작하겠습니다. 다른 플러그인과의 충돌을 피하기 위해 설명적이고 고유한 폴더 이름을 선택하는 것이 중요합니다. 플러그인 이름이 다소 일반적인 경우 고유한 접두사를 추가하는 것이 좋습니다.
github-api/ readme.txt github-api.php
readme.txt
에는 플러그인에 대한 메타 데이터가 포함되어 있으며, 플러그인을 게시하기로 결정한 경우 wordpress.org
에 표시됩니다. 문서에서 WordPress 플러그인 게시에 대해 읽거나 포괄적인 샘플 readme.txt를 확인하십시오.
PHP 파일에는 대시보드에 플러그인에 대한 정보를 표시하는 데 사용되는 헤더의 일부 메타 데이터도 포함되어 있습니다. 다음과 같은 헤더로 시작하십시오.
<?php /** Plugin Name: GitHub API description: >- Add GitHub project information using shortcode Version: 1.0 Author: Your Name License: GPLv2 or later Text Domain: github-api */
보안상의 이유로 다음과 같이 파일에 대한 직접 액세스를 거부하는 것도 좋은 생각입니다.
defined( 'ABSPATH' ) or die( 'No script kiddies please!' );
이 시점에서 플러그인은 아무 작업도 수행하지 않지만 파일을 wp-content/plugins
에 복사하면 플러그인 목록에 나타나야 하고 활성화할 수 있어야 합니다.

다음으로 API 요청을 처리할 라이브러리를 포함하려고 합니다. 다음 코드 예제에는 KNP Labs의 PHP GitHub API가 포함되어 있지만 knplabs/github-api
를 사용 중인 패키지로 대체하여 모든 종속성을 포함할 수 있습니다.
$ cd wp-content/plugins/github-api $ composer require knplabs/github-api
이제 파일 구조는 다음과 같아야 합니다.
github-api/ composer.json composer.lock github-api.php readme.txt vendor/
이제 파일이 준비되었으므로 설치할 때 생성된 vendor/autoload.php
가 필요합니다.
require_once 'vendor/autoload.php';
모든 것이 올바르게 설정되었으면 치명적인 오류가 발생하지 않고 라이브러리에서 클래스를 인스턴스화할 수 있어야 합니다.
$testing = new \Github\Client();
그러나 이것은 종속성을 사용할 수 있는지 테스트하는 빠른 방법일 뿐입니다. 라이브러리를 확장하는 새 클래스를 정의하는 것이 좋습니다.
class MyGithub extends \Github\Client {};
이것은 중요하지 않지만 몇 가지 방법으로 코드를 더 유연하게 만듭니다. 가장 확실한 방법은 필요한 경우 새 기능을 변경하거나 추가할 수 있다는 것입니다. 그러나 코드 전체가 아니라 한 번만 변경해야 하기 때문에 나중에 라이브러리를 전환하려는 경우 삶이 더 쉬워집니다.
워드프레스 단축번호
이제 게시물이나 페이지에 콘텐츠를 배치하여 콘텐츠를 생성할 수 있는 특수 스니펫인 첫 번째 단축 코드를 설정할 차례입니다. 단축 코드를 처음 접하거나 작동 방식에 대해 더 깊이 이해하고 싶다면 공식 단축 코드 문서를 확인하세요. 내 예에서는 작성자가 [github_issues]
단축 코드를 배치할 때마다 GitHub 문제 목록을 표시하겠습니다.
이전과 마찬가지로 API 호출 작업을 수행하기 전에 단축 코드가 올바르게 등록되었는지 확인하기 위해 최소한의 예제부터 시작하겠습니다.
function github_issues_func( $atts ) { return "Hello world!"; } add_shortcode( "github_issues", "github_issues_func" );
이제 [github_issues]
가 포함된 페이지를 게시하면 페이지를 방문할 때 "Hello world"가 표시되어야 합니다. 이제 작동하므로 API 호출을 설정해 보겠습니다.
이전 섹션에서는 GitHub 라이브러리에 대한 자동 로드를 설정하고 이를 확장하기 위해 자체 클래스를 정의했습니다. 이제 이를 사용하여 API 호출을 시작할 수 있습니다. 그래서 우리는 이것을 단축코드의 콜백 함수에 추가할 것입니다. 개념 증명으로 GitHub Pipeline 리포지토리의 모든 문제를 가져와 보겠습니다. 이 방법에 대한 설명서를 사용할 수 있습니다.
function github_issues_func( $atts ) { // Instantiate our class $gh = new MyGithub(); // Make the API call to get issues, passing in the GitHub owner and repository $issues = $gh->api('issue')->all('TransitScreen', 'wp-github-pipeline'); // Handle the case when there are no issues if ( empty($issues) ) return "<strong>" . __("No issues to show", 'githup-api') . "</strong>"; // We're going to return a string. First, we open a list. $return = "<ul>"; // Loop over the returned issues foreach( $issues as $issue ) { // Add a list item for each issue to the string // (Feel free to get fancier here) // Maybe make each one a link to the issue issuing $issue['url] ) $return .= "<li>{$issue['title']}</li>"; } // Don't forget to close the list $return .= "</ul>"; return $return; } add_shortcode( 'github_issues', 'github_issues_func' );
이제 위에서 단축 코드를 테스트하는 데 사용한 것과 동일한 페이지를 볼 수 있어야 하며 이번에는 정렬되지 않은 문제 목록이 표시되어야 합니다. 하지만 기다려! 계속 진행하기 전에 코드를 더 쉽게 테스트할 수 있도록 한 가지 최적화를 수행해 보겠습니다. (테스트 중이시죠?!) GitHub 라이브러리 클래스를 인스턴스화하기 위해 함수에서 new
를 사용하는 대신 매개변수로 전달하고 필요한 경우에만 인스턴스화합시다.
function github_issues_func( $atts, $gh=null ) { // Conditionally instantiate our class $gh = ( $gh ) ? $gh : new MyGithub(); …
이 수정은 종속성 주입 패턴과 유사하여 함수를 훨씬 쉽게 테스트할 수 있습니다. WordPress 단위 테스트는 이 자습서의 범위를 벗어납니다. 그러나 이 새 버전을 사용하면 "가짜" API 데이터를 함수에 쉽게 전달하여 테스트의 주장이 정확히 무엇을 예상해야 하는지 알 수 있도록 하는 방법을 쉽게 알 수 있습니다.
우리가 지금까지 만든 것은 단일 저장소에서만 사용되는 내부 프로젝트에 적합하지만 사용자가 문제를 가져올 저장소를 구성할 수 있다면 훨씬 더 유용할 것입니다. 설정해 보겠습니다.
먼저 WordPress 후크를 사용하여 새 설정 페이지를 등록하고 콜백 함수가 메뉴의 레이블과 제목을 정의합니다. 동일한 증분 방식을 사용하여 작동하도록 하겠습니다.
// Register the menu. add_action( "admin_menu", "gh_plugin_menu_func" ); function gh_plugin_menu_func() { add_submenu_page( "options-general.php", // Which menu parent "GitHub", // Page title "GitHub", // Menu title "manage_options", // Minimum capability (manage_options is an easy way to target administrators) "github", // Menu slug "gh_plugin_options" // Callback that prints the markup ); } // Print the markup for the page function gh_plugin_options() { if ( !current_user_can( "manage_options" ) ) { wp_die( __( "You do not have sufficient permissions to access this page." ) ); } echo "Hello world!"; }
이제 대시보드에 로그인하여 "설정" 아래의 새 GitHub 메뉴를 볼 수 있어야 합니다. 그런 다음 클릭하여 "Hello world!"가 있는 빈 설정 페이지를 볼 수 있습니다.

다음으로 Hello word
를 양식의 실제 마크업으로 교체합니다. 원하는 만큼 스타일을 지정할 수 있는 기본 예를 보여 드리겠습니다.
?> <form method="post" action="<?php echo admin_url( 'admin-post.php'); ?>"> <input type="hidden" name="action" value="update_github_settings" /> <h3><?php _e("GitHub Repository Info", "github-api"); ?></h3> <p> <label><?php _e("GitHub Organization:", "github-api"); ?></label> <input class="" type="text" name="gh_org" value="<?php echo get_option('gh_org'); ?>" /> </p> <p> <label><?php _e("GitHub repository (slug):", "github-api"); ?></label> <input class="" type="text" name="gh_repo" value="<?php echo get_option('gh_repo'); ?>" /> </p> <input class="button button-primary" type="submit" value="<?php _e("Save", "github-api"); ?>" /> </form> <?php
내가 포함시킨 CSS 클래스는 WordPress의 코어에서 사용하는 클래스와 일치하므로 추가 노력 없이도 사용자 지정 옵션 페이지를 보기 좋게 만들 수 있습니다.


이 양식에 대해 두 가지 중요한 사항을 이해해야 합니다. 먼저 제출하는 엔드포인트는 /wp-admin/admin-post.php
여야 합니다. 이 경로를 하드코딩할 수 있지만 웹사이트가 하위 디렉토리에 설치된 경우 작동하지 않습니다. 따라서 내장된 admin_url()
을 사용하여 동적으로 생성합니다.
두 번째로 action
이라는 이름의 숨겨진 입력을 확인하십시오. 이 필드는 WordPress가 양식에 의해 제출된 게시물 요청으로 무엇을 해야 하는지 아는 방법입니다. value
은 콜백 함수를 설정하는 데 사용할 작업 후크의 이름에 해당합니다. 우리가 연결할 작업의 이름은 admin post
접두사가 붙은 이 값이 됩니다. 따라서 우리의 경우 다음을 추가해야 합니다.
add_action( 'admin_post_update_github_settings', 'github_handle_save' );
나는 이것이 사용자 정의 관리 메뉴를 만드는 데 있어 더 기발하고 덜 직관적인 측면 중 하나라고 생각하지만 일단 익숙해지면 꽤 고통스럽지 않습니다. 짐작하셨겠지만, add_action()
의 두 번째 매개변수는 실제로 값을 데이터베이스에 저장할 콜백 함수의 이름입니다.
function github_handle_save() { // Get the options that were sent $org = (!empty($_POST["gh_org"])) ? $_POST["gh_org"] : NULL; $repo = (!empty($_POST["gh_repo"])) ? $_POST["gh_repo"] : NULL; // Validation would go here // Update the values update_option( "gh_repo", $repo, TRUE ); update_option("gh_org", $org, TRUE); // Redirect back to settings page // The ?page=github corresponds to the "slug" // set in the fourth parameter of add_submenu_page() above. $redirect_url = get_bloginfo("url") . "/wp-admin/options-general.php?page=github&status=success"; header("Location: ".$redirect_url); exit; }
예제도 아주 적습니다. 프로덕션 설정에서는 일부 유효성 검사를 추가할 수 있습니다. 또한 이 예에서는 자동으로 status=success
를 URL로 다시 전달합니다. 양식의 마크업은 아직 실제로 사용하지 않습니다. 조건부로 성공 메시지를 표시하려면 gh_plugin_options()
형식 위에 다음과 같은 것을 추가합니다.
if ( isset($_GET['status']) && $_GET['status']=='success') { ?> <div class="updated notice is-dismissible"> <p><?php _e("Settings updated!", "github-api"); ?></p> <button type="button" class="notice-dismiss"> <span class="screen-reader-text"><?php _e("Dismiss this notice.", "github-api"); ?></span> </button> </div> <?php }
유효성 검사를 추가하는 경우 이 동일한 패턴을 사용하여 다른 상태와 메시지를 다시 전달하여 사용자가 양식 제출이 실패했는지 여부와 이유를 알 수 있도록 합니다.
이제 새 소유자 및 저장소 값을 저장할 수 있습니다. GitHub에서 공개 프로젝트의 소유자와 저장소를 입력하여 테스트하십시오. 마지막 단계는 단축 코드 콜백 함수 github_issues_func()
로 돌아가 하드코딩된 소유자 및 저장소 값을 바꾸는 것입니다.
… $issues = $gh->api("issue")->all(get_option("gh_org"), get_option("gh_repo")); …
이것이 준비되면 단축 코드를 추가한 페이지를 다시 방문하십시오. 이제 설정한 프로젝트의 문제가 표시되어야 합니다.
보너스 라운드: OAuth 2.0 인증
위에서 사용한 접근 방식은 공개 리포지토리에서 잘 작동하지만 인증이 필요한 비공개 리포지토리와 함께 이 플러그인을 사용하려면 어떻게 해야 할까요? GitHub API는 OAuth 2.0 프로토콜을 사용하여 인증합니다. OAuth 2.0 프로토콜은 오늘날 가장 많이 사용되는 API로 작업하게 될 것입니다. 기본 OAuth 2.0 워크플로는 다음과 같습니다.
- 공급자에 응용 프로그램(때로는 "클라이언트"라고도 함)을 등록하고 고유 ID와 비밀 키를 받습니다.
- 귀하의 애플리케이션은 공급자의 인증 엔드포인트에 요청을 하고, 위의 자격 증명과 공급자가 요청을 애플리케이션의 엔드포인트로 다시 리디렉션하는 데 사용하는 리디렉션 URL을 전달합니다.
- 그러면 사용자에게 액세스 요청을 수락하라는 메시지가 표시됩니다. 그러한 경우 공급자는 요청과 함께 보낸 URL을 사용하여 사용자를 임시 코드와 함께 애플리케이션으로 다시 리디렉션합니다.
- 애플리케이션은 이 코드를 캡처한 다음 두 번째 요청을 수행하여 이 코드를 공급자에게 다시 전달합니다. 공급자는 액세스 토큰으로 응답하고 애플리케이션은 이 토큰을 사용하여 공급자를 인증합니다.
GitHub에 애플리케이션을 등록하는 것부터 시작하겠습니다. 가장 많이 사용되는 API와 마찬가지로 이 섹션은 웹사이트의 개발자 영역에 있습니다.

여기서 가장 중요한 것은 인증 콜백 URL입니다. 3단계에서 전달된 리디렉션 URL은 여기에 입력한 것과 일치하거나 포함해야 합니다. 그래서 개발을 하다보면 보통 홈페이지에 들어가게 됩니다. 이렇게 하면 내 앱이 모든 경로로 리디렉션될 수 있습니다.
다음으로, 애플리케이션의 클라이언트 ID와 비밀을 제출하기 위해 gh_plugin_options()
에서 설정 페이지에 두 번째 양식을 추가합니다.
<form method="post" action="<?php echo admin_url( 'admin-post.php'); ?>"> <input type="hidden" name="action" value="oauth_submit" /> <h3>Oauth 2.0</h3> <p> <label><?php _e("GitHub Application Client ID:", "github-api"); ?></label> <input class="" type="text" name="client_id" value="<?php echo get_option('client_id')?>" /> </p> <p> <label><?php _e("GitHub Application Client Secret:", "github-api"); ?></label> <input class="" type="password" name="client_secret" value="<?php echo get_option('client_secret')?>" /> </p> <input class="button button-primary" type="submit" value="<?php _e("Authorize", "github-api"); ?>" /> </form>
삶을 더 쉽게 만들기 위해 League of Extraordinary Packages의 OAuth 2.0 클라이언트용 GitHub 공급자를 사용하겠습니다. 따라서 먼저 Composer를 다시 사용하여 종속성을 추가해 보겠습니다.
composer require league/oauth2-github
KNP Labs의 GitHub 라이브러리에도 OAuth 2.0 지원이 내장되어 있습니다. 따라서 제 특정 예에서는 이것이 다소 중복됩니다. 그러나 이 라이브러리는 강력한 League of Extraordinary Packages에서 유지 관리하는 동일한 프레임워크를 모두 확장하는 공급자별 OAuth 2.0 클라이언트 라이브러리 제품군에 속하기 때문에 이 라이브러리를 소개하고 싶었습니다. 지원되는 공급자의 전체 목록을 보거나 새 공급자를 지원하도록 프레임워크를 확장하는 방법에 대한 지침을 읽을 수 있습니다.
사용자가 양식을 제출할 때 토큰을 요청하고 저장하는 함수를 만들어 보겠습니다. GitHub는 이미 지원되는 공급자 중 하나이므로 몇 가지 수정만 하면 해당 설명서의 예제를 복사할 수 있습니다.
function handle_oauth() { // If the form was just submitted, save the values // (Step 1 above) if ( isset($_POST["client_id"]) && isset($_POST["client_secret"]) ) { update_option( "client_id", $_POST["client_id"], TRUE ); update_option("client_secret", $_POST["client_secret"], TRUE); } // Get the saved application info $client_id = get_option("client_id"); $client_secret = get_option("client_secret"); if ($client_id && $client_secret) { $provider = new League\OAuth2\Client\Provider\Github([ "clientId" => $client_id, "clientSecret" => $client_secret, "redirectUri" => admin_url("options-general.php?page=github"), ]); } // If this is a form submission, start the workflow // (Step 2) if (!isset($_GET["code"]) && $_SERVER["REQUEST_METHOD"] === "POST") { // If we don't have an authorization code, then get one $authUrl = $provider->getAuthorizationUrl(); $_SESSION["oauth2state"] = $provider->getState(); header("Location: ".$authUrl); exit; // Check given state against previously stored one to mitigate CSRF attack // (Step 3 just happened and the user was redirected back) } elseif (empty($_GET["state"]) || ($_GET["state"] !== $_SESSION["oauth2state"])) { unset($_SESSION["oauth2state"]); exit("Invalid state"); } else { // Try to get an access token (using the authorization code grant) // (Step 4) $token = $provider->getAccessToken("authorization_code", [ "code" => $_GET["code"] ]); // Save the token for future use update_option( "github_token", $token->getToken(), TRUE ); } }
그리고 다른 폼과 마찬가지로 액션 훅을 추가하여 폼이 저장될 때 함수가 호출되도록 해야 합니다.
add_action( "admin_post_oauth_submit", "handle_oauth" );
이제 양식을 저장하면 API 제공자의 승인 페이지로 이동합니다. 승인 후 애플리케이션은 저장된 토큰을 사용하여 액세스 권한이 있는 개인 리포지토리에서 데이터를 요청할 수 있습니다. 내가 KNP Labs에서 사용하는 라이브러리에는 이를 위한 편리한 방법이 있습니다.
$gh = new MyGithub(); $gh->authenticate( get_option("github_token"), NULL, Github\Client::AUTH_HTTP_TOKEN);
라이브러리는 인증을 처리하는 방식에 따라 다르지만 어떤 식으로든 토큰을 전달하면 사용자를 대신하여 인증된 요청이 생성됩니다.
결론
우리는 많은 근거를 다루었고 전체 워크플로가 명확하게 유지되도록 예제를 가능한 최소화하려고 노력했습니다. 이 자습서의 전체 소스 코드를 사용할 수 있습니다. 이제 타사 서비스 API를 사용하는 WordPress 플러그인 생성과 관련된 움직이는 부분을 명확하게 이해하고 자신의 WordPress API 플러그인을 작성하는 데 영감을 받았으면 합니다.
최종 메모
- 워드프레스 코덱스(문서)
- GitHub API(문서)
- OAuth 2.0(문서)
- 작곡가(문서)
- 특별 패키지 리그
- Guzzle 문서