WordPressAPI開発者が使用していない5つのバトルテスト済みテクニック

公開: 2022-03-11

少なくともクライアントの目から見て、WordPress開発者としてのステータスを高めるための最良の方法の1つは、APIの使用に熟練することです。 WordPress API実装の一般的なシナリオは次のとおりです。クライアントから、サイトにウィジェットを追加するように求められます。たとえば、電子メールサブスクリプションウィジェットなどです。 サードパーティの電子メールサービス(おそらくスクリプトタグまたはiframe )からコードを取得してページに貼り付け、クライアントに「了解しました」と返信します。

残念ながら、あなたはやや要求の厳しいクライアントを扱っており、彼らは次の欠陥に気づきます。

  • ウィジェットは、サイトの他の部分と同様に、サンセリフフォントを備えていますが、完全に正しいフォントではありません。 ウィジェットは、インストールしたカスタムフォントの代わりにHelveticaを使用しています。
  • ウィジェットのサブスクリプションフォームは、新しいページの読み込みをトリガーします。これは、記事の途中に配置すると混乱を招く可能性があります。
  • ウィジェットは、ページの残りの部分の後にロードするのに余分な時間がかかるようですが、これは不快で安価な感じがします。
  • クライアントは、サブスクライバーがサブスクライブした投稿に基づいてメタデータでタグ付けされることを望んでおり、ウィジェットはこの機能にリモートで類似したものを提供しません。
  • クライアントは、2つのダッシュボード(wp-adminと電子メールサービスの管理領域)を管理する必要があることに煩わしいと感じています。

この時点で、2つのことのいずれかが合理的に発生する可能性があります。 これらのアイテムを「必要なもの」と宣言して、80/20ソリューションのメリットについてクライアントを安心させるか、これらの要求に応えることができます。 私の個人的な経験では、そのようなリクエストを提供すること、つまりサードパーティのサービスを習得していることを示すことは、あなたが一種のWordPressウィザードであることをクライアントに納得させるための信頼できる方法であることがわかりました。 さらに、それはしばしば楽しいことです。

過去10年間、私はWordPressをおそらく50の異なるAPIに対するAPI消費のプラットフォームとして使用してきました。 最も一般的なAPIには、MailChimp、Google Analytics、Google Maps、CloudFlare、Bitbucketなどがあります。 しかし、さらに多くのことを行う必要がある場合、カスタムソリューションが必要な場合はどうなりますか?

WordPressAPIクライアントを開発する方法

この記事では、一般的な「電子メールサービス」APIに対して開発を行い、可能な限り不可知論を維持するように最善を尽くします。 ただし、JSONRESTAPIを扱っていると想定するのは妥当だと思います。 この記事の技術的なポイントを楽しむのに役立つ可能性のある背景トピックを次に示します。

  • WordPressHTTPファミリーの関数
  • JSON
  • 残り

これらのトピックに少し慣れていて、さらに深く掘り下げることに興味がある場合は、今すぐ一時停止して、優れたPostmanアプリケーションをダウンロードしてください。 コードを記述せずにAPIと通信できます。

Postmanのダッシュボードのスクリーンショット

郵便配達員。 たぶん私のお気に入りの開発ツール?

ただし、それらにまったく精通していない場合は、とにかく読み続けてください。 ある程度のWordPressの経験を持つ技術的な聴衆は、この記事を最大限に活用しますが、私は、技術的ではない方法で各技術の価値を説明するように注意します。 技術者以外の読者は、この記事を後援する前に各ポイントのROIを評価し、提供された後の実装の品質を判断できるようにします。

注:簡単な復習コースが必要な場合は、WordPressRESTAPIガイドを確認してください。

これ以上の前文はありませんが、私が協力しているほとんどすべてのAPI、プロジェクト、およびチームで私が評価しているいくつかの異なる手法をあなたと共有させてください。

過渡現象:それらを保持するタイミング、それらを折りたたむタイミング

私の冒頭の段落で、クライアントが2つの管理領域(wp-adminと電子メールサービスのダッシュボード)にまたがるのが面倒だと感じたことに気づきました。 これを解決する良い方法は、最近のサブスクライバーアクティビティのダイジェストを表示するために、wp-adminのダッシュボードウィジェットを提供することです。

wp-adminダッシュボードウィジェットのスクリーンショット

クライアントがサードパーティの電子メールサービスプロバイダーにアクセスする手間を省くために、WordPress内で提供する可能性のあるダッシュボードUIのタイプの例。

ただし、これもリモートAPI(メールサービスによって提供されるAPI)への複数のHTTPリクエストを必要とし、ページの読み込みが長くなる可能性があります。 このパフォーマンスの問題の解決策は、API呼び出しをトランジェントとして保存することです。 このコーデックスの記事は、あなたが間違いなく読むべき素晴らしい説明を提供しますが、私はそれをこのように要約します:

  1. リモートAPIからデータを取得します。
  2. set_transient()を使用して、パフォーマンス、レート制限、およびこの特定のアプリケーションで古いデータを表示する際のエラーの許容範囲に関する独自の判断に基づいて、選択した有効期限で保存します。
  3. ビジネスロジックを続行します。データを処理し、どのような場合でも値を返します。
  4. 次のページの読み込み時など、データが再度必要になった場合は、APIからデータを取得する必要があると判断する前に、 get_transient()を使用して一時キャッシュでデータを確認してください。

これは有用で実行可能な基盤であると思いますが、REST動詞について少し考えれば、さらに一歩進めることができます。 最も一般的な5つのメソッド(GET、POST、PATCH、PUT、DELETE)のうち、一時キャッシュに属するのはそのうちの1つだけです。 どれを推測できますか? GETです。 私のプラグインには、ほとんどの場合、問題のリモートAPIへの呼び出しを抽象化するための専用のPHPクラスがあり、そのクラスをインスタンス化するときの引数はHTTPメソッドです。 GET呼び出しでない場合は、キャッシングレイヤーをまったく呼び出しません。

さらに、それがGET呼び出しでない場合は、電子メールサブスクライバーを追加、編集、または削除するなど、何らかの方法でリモートデータを変更するためのアクションを実行しているのは当然のことです。 これは、 delete_transient()を使用して、そのリソースの既存のキャッシュを無効にする良い機会かもしれません。

WordPressメールサブスクリプションAPIの例に戻ると、これが実際にどのように機能するかを次に示します。

  • 最近のサブスクライバーを表示するためのダッシュボードウィジェットは、GETリクエストを介して/subscribersのAPIエンドポイントを呼び出します。 これはGETリクエストであるため、一時キャッシュに保存されます。
  • メーリングリストに登録するためのサイドバーウィジェットは、POSTリクエストを介して/subscribersのAPIエンドポイントを呼び出します。 これはPOSTリクエストであるため、一時キャッシュを回避するだけでなく、一時キャッシュの関連部分を削除するように促し、ダッシュボードウィジェットにこの新しいサブスクライバーが反映されるようにします。
  • トランジェントに名前を付けるときは、呼び出しているリモートAPIURLにちなんで文字通り名前を付けることで整理することがよくあります。 これは、削除する正しいトランジェントを識別するための便利な方法です。 引数を取るエンドポイントの場合は、それらを文字列に連結し、一時的な名前にも追加します。

クライアントまたはその他のあまり技術的でない利害関係者として、アプリケーションがリモートサービスからデータをプルするときはいつでも、一時的なキャッシュを具体的に要求するか、少なくともその議論を行う必要があります。 トランジェントがどのように機能しているかを確認するには、優れたクエリモニタープラグインに精通している必要があります。 これにより、一時的なものとして隠されているデータ、頻度、および期間を参照するためのインターフェイスが提供されます。

トランジェントが十分でない場合があります

一部のプレミアムWordPressホスティングサービスでは、実際には本番環境でトランジェントを使用できません。 おそらくMUプラグインまたはその他のスクリプトの形式でコードが実行されており、トランジェントAPIを使用する試みをインターセプトし、代わりにオブジェクトキャッシュを介してその情報を保存します。 最も一般的な構成のWP-Engineは、この典型的な例です。

キャプションで説明されているphpMyAdminビューのスクリーンショット

phpMyAdmin UIの憂慮すべき光景:一時的なものが完全にない本番サイト? これは、オブジェクトのキャッシュが機能していることを意味している可能性があります。

単にデータを保存および取得している場合は、実際にはこれを気にする必要はなく、データが発生していることに気付くことさえありません。 *_transient()関数のファミリー全体が同じ最終結果を提供し、一時キャッシュの代わりにオブジェクトキャッシュを使用するようにフィルター処理されます。 ただし、問題が発生する可能性があるのは、トランジェントを削除しようとしたときです。 これが理由です。

API統合が複雑で、独自の設定ページに値する場合は、UIを含めて、管理者ユーザーがプラグインの一時キャッシュ全体をクリアできるようにすることができます。 このボタンの最も一般的な使用法は、クライアントがリモートサービスで直接データを変更し、WordPressに保存しているキャッシュを無効にしたい場合です。 このボタンは、クライアントがアカウントのクレデンシャル、APIキーを変更する場合、または一般的にデバッグ用の「ファクトリリセット」ボタンとしても役立つ場合があります。

オプションボタンのスクリーンショット

クライアントがAPIデータのローカルキャッシュを空にできるようにするためのUIの例。

すべての一時キーに名前空間を設定して、 delete_transient()でそれぞれを識別できるようにしたとしても、最良のシナリオにはおそらく生のSQLが含まれます。これは、WordPressでは常に避けようとしています。

 <?php // Purge all the transients associated with our plugin. function purge() { global $wpdb; $prefix = esc_sql( $this -> get_transient_prefix() ); $options = $wpdb -> options; $t = esc_sql( "_transient_timeout_$prefix%" ); $sql = $wpdb -> prepare ( " SELECT option_name FROM $options WHERE option_name LIKE '%s' ", $t ); $transients = $wpdb -> get_col( $sql ); // For each transient... foreach( $transients as $transient ) { // Strip away the WordPress prefix in order to arrive at the transient key. $key = str_replace( '_transient_timeout_', '', $transient ); // Now that we have the key, use WordPress core to the delete the transient. delete_transient( $key ); } } ?>

便利ではなく、効率的でもありません。 代わりに、オブジェクトキャッシングは、キャッシュされた値をグループ化する便利な方法を提供するため、この状況ではオブジェクトキャッシングが必要になります。 このように、プラグインに関連するすべてのキャッシュ値を空にする必要がある場合は、 wp_cache_delete( $key, $group )への単純なワンライナー呼び出しです。

このすべてを要約すると、次のようになります。APIのデータのキャッシュ管理の専門家でない場合は、APIの使用の専門家になることはできません。

クライアントとして注意すべき重要なことは、ステージング環境と本番環境の間の異常なキャッシュ動作です。 つまり、ステージングで新しいバッチの作業をテストすることは常に良い習慣ですが、キャッシングは本番環境でも同様の注意を払ってテストする必要があります。

リモートAPIは、PHPクラス階層への通知に役立ちます

プラグインのさまざまなPHPクラスをレイアウトするとき、APIエンドポイントの定義方法を模倣すると便利なことがよくあります。たとえば、次のエンドポイントに共通していると思われるものは何ですか。

  • https://api.example-email-service.com/v1/subscribers.json
  • https://api.example-email-service.com/v1/lists.json
  • https://api.example-email-service.com/v1/campaigns.json

それらはすべてコレクションを返します。これは、GETリクエストの結果を意味し、各結果が配列のメンバーである0から多の結果を返します。 これはかなり明白に聞こえるかもしれませんが、PHPコードで次のクラス構造を作成するための便利なプロンプトであることがわかりました。

  • class.collection.php 、抽象クラス
  • class.subscribers.phpは、抽象クラスCollectionを拡張します。
  • class.lists.phpは、抽象クラスCollectionを拡張します。
  • class.campaigns.phpは、抽象クラスCollectionを拡張します。

抽象クラスは、その唯一の引数として、ページネーション、列の並べ替え、順序の並べ替え、検索フィルターなどのクエリパラメーターの配列を取ります。 リモートAPIの呼び出し、エラーの処理、結果をHTMLの<select>メニューまたはjQueryUIAutoSuggestにモーフィングするなどの一般的なタスクのメソッドが含まれます。 抽象クラスをインスタンス化するクラスは非常に短い可能性があり、おそらく*.jsonエンドポイントURLで使用する文字列を指定するだけです。

MailchimpAPIプレイグラウンドのスクリーンショット

Mailchimpは、サンドボックスAPI呼び出しなどのためのAPI「遊び場」を公開しています。 また、APIのデータ階層全体をサーフィンするための便利な方法としても機能し、独自のクラス階層を構築する方法を垣間見ることができます。

同様に、次のエンドポイントに共通するものは何ですか?

  • https://api.example-email-service.com/v1/subscribers/104abyh4.json
  • https://api.example-email-service.com/v1/lists/837dy1h2.json
  • https://api.example-email-service.com/v1/campaigns/9i8udr43.json

それらはすべてアイテムを返します。これは、コレクションの1つの特定の一意のメンバーを意味します。たとえば、1つの特定の電子メールサブスクライバー、1つの電子メールリスト、または1つの電子メールキャンペーンなどです。 したがって、PHPコードでは次の構造を使用するのが好きです。

  • class.item.php 、抽象クラス
  • class.subscriber.phpは、抽象クラスItemを拡張します。
  • class.list.phpは、抽象クラスItemを拡張します。
  • class.campaign.phpは、抽象クラスItemを拡張します。

抽象クラスは、要求されている特定のアイテムを識別するための文字列を唯一の引数として取ります。 繰り返しになりますが、インスタンス化されるクラスは非常に短い可能性があり、おそらく*/duy736td.jsonで使用する文字列を指定するだけです。

クラス継承を構造化する方法はたくさんありますが、上記で概説した方法とは異なる方法を採用したとしても、リモートAPIの構造がアプリケーションの構造に役立つ可能性は十分にあります。

クライアントとして、貧弱なアーキテクチャの一般的な症状は、アプリケーション全体で同じ変更を何度も要求しなければならないことに気付いた場合です。 たとえば、レポートがページごとに10ではなく100の結果を返すように要求し、サブスクライバーレポート、キャンペーンレポート、サブスクライブ解除レポートなどに対してその要求を繰り返し続ける必要がある場合、クラスアーキテクチャが不十分であることが検出される可能性があります。 この状況では、リファクタリングサイクルの恩恵を受けるかどうかをチームに尋ねる価値があります。目標は製品の動作を変更することではなく、動作を変更しやすくするために基盤となるコードを改善することです。将来の製品の。

WP_Errorの完璧なユースケース

コードでWP_Errorファミリーの関数を適切に使用し始めるのに必要な時間よりも、何年もかかったことを認めるのは恥ずかしいことです。 プログラムで気にする価値のあるエラーが決してないことを前提として、またはケースバイケースでそれらを処理することを前提として、私は自分のやり方をコード化する傾向がありました。 リモートAPIを使用すると、レーザービームのようにその精神が失われます。これは、 WP_Errorを使用するための非常に便利で強力なユースケースを提供するためです。

先ほど、リモートAPIにHTTPリクエストを送信することを目的としたPHPクラスがあることを思い出してください。 すべての定型文、すべてのデータ操作、すべての二次的な懸念を取り除くと、そのクラスは実際には、APIからHTTP応答オブジェクトを取得するためにwp_remote_request()を呼び出すことになります。 便利なことに、 wp_remote_request()は、何らかの理由で呼び出しが実行に失敗した場合、代わりにWP_Errorを返しますが、呼び出しが好ましくないタイプのHTTP応答を返すことに成功した場合はどうでしょうか。

サブスクリプションフォームのスクリーンショット

技術的に言えば、API呼び出しは機能しましたが、警告がまったくないわけではありません。 これらの警告は、コードベース全体で一貫した方法でキャプチャおよび報告する必要があります。

例として、 /lists.jsonエンドポイントを呼び出した可能性がありますが、この特定のアカウントにはまだリストが設定されていません。 これにより、有効なHTTP応答が返されますが、ステータスコードは400になります。これ自体は致命的なエラーではありませんが、このAPI呼び出しをドロップダウンメニューに変換するフロントエンドコードの観点からすると、400は同様にWSODになります! したがって、 wp_remote_request()の結果に対して追加の解析を実行すると、結局WP_Errorが返される可能性があるので便利です。

 <?php function call() { $response = wp_remote_request( $this -> url, $this -> args ); $code = wp_remote_retrieve_response_code( $response ); $first_digit = $code[0]; $good_responses = array( 2, 3 ); if( ! in_array( $first_digit, $good_responses ) { $body = wp_remote_retrieve_body( $response ); $out = new WP_Error( $code, $body ); } else { $out = $response; } return $out; } ?>

このパターンは、出力を続行する前にis_wp_error()に安全に依存できることがわかっているため、呼び出し元クラスを呼び出すコードを単純化するのに役立ちます。

クライアントとして、悪意のあるユーザー、混乱したユーザー、せっかちなユーザーの役割を果たす必要がある場合があります。 使用することを意図していない方法でアプリを使用してください。 開発者があなたに望んでいないように思われることをしてください。 何が起こるかに注意してください。 役立つエラーメッセージが表示されますか? エラーメッセージは表示されますか? そうでない場合は、より良いエラー処理を回避する一連の作業を後援する価値があるかもしれません。

ob_get_clean()の美しいデバッグ能力

ほぼすべてのサイトが他のサイトのAPIを消費し、それ自体が独自のAPIを介して消費される、最新のプログラム可能なWebは、コードの非常に強力な領域になっています。 しかし、それを非常に遅くする可能性があるのは、まさにこの品質です。

リモートHTTPリクエストは、特定のページ読み込みの中で最も時間のかかる部分であるのが一般的です。 このため、多くのAPI駆動型コンポーネントはAjaxまたはcronのいずれかを介して実行されます。 たとえば、電子メールサブスクライバーのリストを検索するためのオートサジェストは、ページのロード時にDOM内の100,000のサブスクライバーすべてをロードするのではなく、キーストロークごとにリモートデータソースにオンデマンドでpingを実行する必要があります。 それがオプションでない場合は、おそらく大きなクエリが夜間のcronタスクで同期される可能性があるため、リモートAPIではなくローカルミラーから結果を取得できます。

このアプローチの問題は、デバッグが難しい場合があることです。 単にWP_DEBUGをオンにして、エラーメッセージをブラウザウィンドウに表示させる代わりに、ブラウザのネットワークコンソールを確認したり、cronタスク(うまくいけば?)の実行中にログファイルを追跡したりします。 これは不快だと思います。

この状況を改善する1つの方法は、 error_log()を注意深く戦略的に呼び出すことです。 しかし、繰り返しになりますが、ロギングに関する一般的な問題は、大規模またはビジーなアプリケーションでは、エラーログが大きくなりすぎたり、急速に大きくなりすぎて、監視や解析に役立たない可能性があることです。 したがって、実際のアプリケーションロジックの場合と同じように、ログに記録する内容を選択し、それに十分な考慮を払う必要があります。 特定の配列メンバーをログに記録できなかったために、バグの本質が再び回避されたことに気付くために、まれなcronタスクで断続的にのみ発生するように見えるエキゾチックなエッジケースエラーをログに記録するのに時間をかけたことは残念です、たとえば、問題のある値の。

したがって、私の哲学は、常にログに記録するわけではありませんが、ログに記録する場合はすべてをログに記録するようになりました。 つまり、特に気になる機能を特定した後、できるだけ広いネットでログに記録します。

 <?php function debug( $bug ) { ob_start(); var_dump( $bug ); $out = ob_get_clean(); error_log( $out ); } ?>

これは、 var_dump() 'でバグのある値全体をエラーログファイルの単一のエントリにまとめることになります。

エラーログファイルのスクリーンショット

デバッグするには人間工学的ではないほど大きくなったエラーログ。

クライアントとして、アプリケーションの総ファイルメモリ使用量を定期的にチェックする価値があります。 ホスティングアカウントのストレージ制限に突然突っ込んでいることに気付いた場合は、エラーログが暴走したことが原因である可能性があります。 開発者は、より良いロギングに焦点を合わせた作業サイクルの恩恵を受けるでしょう。そして、顧客も同様に恩恵を受けるでしょう!

正確にはクリックベイトではありませんが、それで十分です

この記事のリスティクル構造はご容赦ください。 これらのパターンは非常に一般的であるため、これらのポイントをより統一された記事のテーマに強制することはできませんでした。これらは、JSONRESTエンドポイントとWordPress出力に適用されます

これらは、リモートAPIが何であるか、またはWordPress内でそれを何に使用しているかに関係なく、何度も発生するパターンです。 私はこれまで、これらすべての種類の原則をプラグインの定型文にまとめて、作業を大幅に加速させてきました。 プロジェクトごとに保持している同様のポイントはありますか? それらを共有して、私がそれらを盗んでボイラープレートに追加できるようにしてください!

関連:現代のWordPress開発へのアプローチ方法(パート1)