「スープからナッツまで」サービスAPIを使用したWordPressプラグインの作成

公開: 2022-03-10
簡単な要約↬ますます多くの公開されているAPIは、アプリケーションの機能を拡張するための強力なサービスを提供します。 WordPressは、信じられないほど動的で柔軟なCMSであり、小さな個人ブログから主要なeコマースWebサイト、およびその間のすべてに電力を供給します。 WordPressを非常に用途の広いものにしている理由の一部は、機能の追加を非常に簡単にする強力なプラグインシステムです。 ショートコードを使用してWordPressページにGitHubAPIからのデータを表示できるプラグインであるGitHubPipelineを作成した方法について説明します。 具体的な例とコードスニペットを示しますが、プラグインを使用してサービスAPIを使用する方法について、ここで説明する手法の青写真を検討してください。 最初から始めますが、WordPressとプラグインの開発にある程度精通していることを前提としており、WordPressやComposerのインストールなどの初心者向けのトピックには時間を費やしません。

ますます多くの公開されているAPIは、アプリケーションの機能を拡張するための強力なサービスを提供します。 WordPressは、信じられないほど動的で柔軟なCMSであり、小さな個人ブログから主要なeコマースWebサイト、およびその間のすべてに電力を供給します。 WordPressを非常に用途の広いものにしている理由の一部は、機能の追加を非常に簡単にする強力なプラグインシステムです。

ショートコードを使用してWordPressページにGitHubAPIからのデータを表示できるプラグインであるGitHubPipelineを作成した方法について説明します。 具体的な例とコードスニペットを示しますが、プラグインを使用してサービスAPIを使用する方法について、ここで説明する手法の青写真を検討してください。

SmashingMagの詳細

  • WordPress Essentials:WordPressプラグインを作成する方法
  • トランジェントを使用してGitHubでWordPressプラグインをデプロイする方法
  • プラグインに構成可能なフィールドを追加するための3つのアプローチ

最初から始めますが、WordPressとプラグインの開発にある程度精通していることを前提としており、WordPressやComposerのインストールなどの初心者向けのトピックには時間を費やしません。

ジャンプした後もっと! 以下を読み続けてください↓

あなたは必要になるでしょう:

  • WordPressの新規インストールを備えたPHP環境。
  • GitHubアカウント(または即興で作成する場合は別のAPIプロバイダー)。
  • Composer(推奨)。

APIの選択

この種のプラグインを作成する最初のステップは、APIを選択することです。 このチュートリアルでは、GitHubAPIを使用します。 別のAPIの使用を検討している場合は、プロジェクトのやりがいに影響を与える可能性のあるいくつかの重要な要素を考慮してください。

私が最初に見ることの1つは、APIのドキュメントの徹底性と品質です。 それがまばらであるか時代遅れであるならば、あなた自身の質問に答えるためにソースコードをふるいにかけることに時間を費やす準備をしてください。 また、APIがどれほど成熟しているか、プロバイダーがどの程度責任を持ってバージョン管理しているかを検討してください。 何か素晴らしいものを作成するために時間を費やすことほど悪いことはありませんが、アップストリームAPIへの変更のためにそれが壊れてしまうだけです。 エンドポイントURLでバージョン管理システムを探します。

 // good https://api.stable.com/v1/user/ // danger https://api.dodgy.com/user/

明らかなことを述べるリスクを冒して、サードパーティのAPIに対するプログラミングには信頼関係が含まれ、すべてのAPIが同じように作成されるわけではありません。

図書館の買い物

確立されたブランドは、APIの操作を容易にするために、ライブラリまたはSDKを配布することがよくあります。 そうでない場合は、移動して車輪の再発明を行う前に、他の誰かがすでにライブラリを作成しているかどうかを調べることを忘れないでください。 GoogleとGitHubは、調査を開始するのに最適な2つの場所です。 GitHubのスターまたはフォークの数は、ライブラリがどれほど効果的であるかを示す良い指標です。 最新のコミットの年齢および/または未解決の問題の数は、それがどれほど積極的に維持されているかを示しています。 私の場合、幸運にもKNPLabsによる素敵なPHPGitHubAPIを見つけました。

ガズルであなた自身を書く

プロバイダーにとって満足のいくライブラリがない場合でも、Guzzleなどのツールを使用するとHTTPリクエストの処理がはるかに簡単になるため、最初から始めるべきではありません。 GuzzleはPHPのcURLライブラリをラップし、手動でのリクエストの構成と作成に通常関連する頭痛の種の多くを取り除きます。 リクエストを1つか2つだけ行う場合でも、コードがより堅牢になるため、これを使用することをお勧めします。Composerを使用してインストールするのは簡単です。

プラグインの設定

まず、最小限のWordPressプラグイン、つまり2つのファイルを含むディレクトリの基本的なスケルトンから始めます。 他のプラグインとの競合を避けるために、わかりやすく一意のフォルダ名を選択することが重要です。 プラグインの名前が一般的なものである場合は、一意のプレフィックスを追加することを検討してください。

 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にコピーすると、プラグインリストに表示され、アクティブ化できるはずです。

WordPressダッシュボードプラグインページ
WordPressダッシュボードプラグインページ。 (拡大版を表示)

次に、APIリクエストを処理するライブラリを含めます。 次のコード例では、KNPLabsのPHPGitHub 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 {};

これは重要ではありませんが、いくつかの点でコードをより柔軟にします。 最も明白な方法は、必要に応じて新しい機能を変更または追加できることです。 ただし、コード全体ではなく1回だけ変更を加える必要があるため、将来ライブラリを切り替えたい場合にも、作業が楽になります。

WordPressショートコード

次に、最初のショートコードを設定します。これは、投稿またはページに配置してコンテンツを生成できる特別なスニペットです。 ショートコードにまったく慣れていない場合、またはショートコードがどのように機能するかをより深く理解したい場合は、公式のショートコードドキュメントを確認してください。 私の例では、作成者がこのショートコードを配置する場所にGitHubの問題のリストを表示します: [github_issues]

前に行ったように、API呼び出しを行う前に、ショートコードが正しく登録されていることを確認するための最小限の例から始めましょう。

 function github_issues_func( $atts ) { return "Hello world!"; } add_shortcode( "github_issues", "github_issues_func" );

これで、 [github_issues]を含むページを公開すると、そのページにアクセスしたときに「Helloworld」が表示されるはずです。 これが機能しているので、API呼び出しを設定しましょう。

前のセクションでは、GitHubライブラリの自動読み込みを設定し、それを拡張するための独自のクラスを定義しました。 これで、API呼び出しを行うためにそれを使用し始めることができます。 そこで、ショートコードのコールバック関数に追加します。 概念実証として、GitHubパイプラインリポジトリ内のすべての問題を取得してみましょう。 このメソッドのドキュメントが利用可能です。

 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' );

これで、ショートコードをテストするために上記で使用したのと同じページを表示できるようになります。今回は、順序付けられていない問題のリストが表示されます。 ちょっと待って! 先に進む前に、コードをテストしやすくするために1つの最適化を行いましょう。 (テスト中ですよね?!)関数でnewを使用してGitHubライブラリクラスをインスタンス化する代わりに、パラメーターとして渡し、必要な場合にのみインスタンス化しましょう。

 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!]のある空白の設定ページが表示されるはずです。

空のWordPressプラグインページ
空のWordPressプラグインページ。 (拡大版を表示)

次に、 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のコアで使用されているものと一致します。これは、追加の作業なしでカスタムオプションページを適切に表示するための優れた方法です。

基本的なスタイルのカスタムWordPress設定ページ
基本的なスタイルのカスタムWordPress設定ページ。 (拡大版を表示)

このフォームについて理解しておくべき2つの重要なことがあります。 まず、送信するエンドポイントは/wp-admin/admin-post.phpである必要があります。 このパスをハードコーディングすることもできますが、Webサイトがサブディレクトリにインストールされている場合は機能しません。 そのため、組み込みのadmin_url()を使用して動的に作成します。

次に、 actionという名前の非表示の入力に注目してください。 このフィールドは、WordPressがフォームによって送信されたPOSTリクエストをどのように処理するかを知る方法です。 このvalueは、コールバック関数を設定するために使用するアクションフックの名前に対応しています。 フックするアクションの名前はこの値になり、接頭辞はadmin postになります。 したがって、この場合、これを追加する必要があります。

 add_action( 'admin_post_update_github_settings', 'github_handle_save' );

これは、カスタム管理メニューを作成する際の、より奇妙で直感的ではない側面の1つだと思いますが、慣れれば、かなり苦痛はありません。 ご想像のとおり、 add_action()の2番目のパラメーターは、実際に値をデータベースに保存するコールバック関数の名前です。

 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")); …

これが整ったら、ショートコードを追加したページに再度アクセスします。 これで、設定したプロジェクトの問題が表示されるはずです。

ボーナスラウンド:OAuth2.0認証

上記で使用したアプローチはパブリックリポジトリには最適ですが、認証が必要なプライベートリポジトリでこのプラグインを使用する場合はどうでしょうか。 GitHub APIは、OAuth 2.0プロトコルを使用して認証します。これは、最近最も人気のあるAPIでの作業に遭遇するものです。 基本的なOAuth2.0ワークフローは次のようになります。

  1. アプリケーション(「クライアント」と呼ばれることもあります)をプロバイダーに登録し、一意のIDと秘密鍵を受け取ります。
  2. アプリケーションはプロバイダーの認証エンドポイントにリクエストを送信し、上記のクレデンシャルと、プロバイダーがリクエストをアプリケーションのエンドポイントにリダイレクトするために使用するリダイレクトURLを渡します。
  3. 次に、ユーザーはアクセス要求を受け入れるように求められます。 その場合、プロバイダーはリクエストとともに送信されたURLを使用して、一時的なコードとともにユーザーをアプリケーションにリダイレクトします。
  4. アプリケーションはこのコードをキャプチャしてから2番目のリクエストを行い、このコードをプロバイダーに返します。 プロバイダーはアクセストークンで応答します。アクセストークンは、アプリケーションがプロバイダーでの認証に使用します。

まず、GitHubにアプリケーションを登録します。 最も一般的なAPIと同様に、このセクションはWebサイトの開発者エリアにあります。

GitHubの新しいアプリケーション登録ページ
GitHubの新しいアプリケーション登録ページ。 (拡大版を表示)

ここで最も重要なことは、承認コールバックURLです。 手順3で渡されたリダイレクトURLは、ここに入力したものと一致するか、それを含める必要があります。 そのため、開発中は通常、Webサイトのホームページに入ります。 このようにして、私のアプリは任意のパスにリダイレクトできます。

次に、アプリケーションのクライアントIDとシークレットを送信するための2番目のフォームを設定ページの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>

生活を楽にするために、The League of ExtraordinaryPackagesのGitHubProvider for OAuth2.0クライアントを使用します。 したがって、最初に、Composerを再度使用して依存関係を追加しましょう。

 composer require league/oauth2-github

KNP LabsのGitHubライブラリにもOAuth2.0サポートが組み込まれていることに注意してください。したがって、私の特定の例では、これはやや冗長です。 しかし、このライブラリは、強力なリーグオブエクストラオーディナリーパッケージによって維持されているのと同じフレームワークをすべて拡張するプロバイダー固有のOAuth 2.0クライアントライブラリのスイートに属しているため、紹介したいと思いました。 サポートされているプロバイダーの完全なリストを表示したり、新しいプロバイダーをサポートするためにフレームワークを拡張する方法についての説明を読んだりできます。

ユーザーがフォームを送信したときにトークンを要求して保存する関数を作成しましょう。 GitHubはすでにサポートされているプロバイダーの1つであるため、いくつかの変更を加えるだけで、ドキュメントの例をコピーできます。

 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プラグインの作成に関連する重要な要素を明確に理解し、独自のWordPressAPIプラグインを作成するように促されたことを願っています。

ファイナルノート

  • WordPressコーデックス(ドキュメント)
  • GitHub API(ドキュメント)
  • OAuth 2.0(ドキュメント)
  • Composer(ドキュメント)
  • 臨時パッケージのリーグ
  • ガズルのドキュメント