web-dev-qa-db-ja.com

ライフサイクル全体を通してWP_Userクラスを拡張し、このサブクラスを使用する

私が達成しようとしているのは以下の通りです:私たちのウェブサイトのすべてのユーザーに対して、私は一度サービスへのAPIリクエスト(他のデータベースと対話するlocal REST AP​​I)をしてユーザーがログアウトして再度ログインするまでWP_User(sub)クラス(この値はアプリケーション内の各ページで1回使用されるため、ページロードごとに1回取得する必要があるため、パフォーマンス上非常に望ましくありません)。

私がこれまでに発見した懸念の分離に関して最もエレガントな方法は、O'Reillyの本WordPressによるWebアプリケーションの構築&Brian Messenlehner&にあるように、WP_Userクラスを拡張(サブクラス化)することによって行われます。ジェイソンコールマン

サンプルコードはここで見られます: 作者のGitHubのこのファイルを見てください

ただし、問題は、このStudent(WP_Userを拡張したサブクラス)をコード内で使用できないことです。現在のユーザーのStudentインスタンスを1つ取得するには、次の方法でインスタンス化する必要があります。

$student = new Student($current_user->ID);

ページ上でこれを行うと、インスタンスは常に再作成され(したがって、タイトルのライフサイクルを参照してください)、$student->assignmentsへの呼び出しは新しいページに移動した後にWP_Userサブクラス自体の内部にキャッシュされることはないページをリロードしているので、すべてのページがロードされるたびに、トラフィックが多い本番環境ではおそらく機能しないAPIとデータベースを使用しています。

WordPress自体の$current_userグローバル変数(これはWP_Userインスタンスです)はログイン直後に作成されたように見え、私の理解する限りではアプリケーション全体を通して利用可能です。私が本当に欲しいのは、アプリケーション全体で同じ可用性が、WP_Userクラスの代わりに私のサブクラス(Student)にあることですが、もっと重要なのは、ログインユーザーごとにAPIヒットが一度だけ行われるようにすることです。ちょうど$current_user->user_loginにあるWP_Userのように)。

私はuser_metaWP_Userを追加することも検討しました、そしてそれに関連してこの質問をチェックアウトしました、それは部分的に役に立つように思われました:

しかし、これはWordPressオブジェクトキャッシュであるwp_cache_getを通して明確に取得されます。

  1. 非永続キャッシュは現在のページのロード中にのみ利用可能です。次のページが読み込まれると、もう一度空白になります。
  2. ストレージサイズは、サーバー上のPHPに使用可能なメモリの合計によって制限されます。大きなデータセットを保存しないでください。さもないと、「メモリ不足」というメッセージが表示される可能性があります。
  3. このタイプのキャッシュを使用することは、ページの作成中に複数回繰り返される操作に対してのみ意味があります。

ページの作成時にStudentサブクラスの値を複数回使用することはありませんが、値はアプリケーションのすべてのページで1回使用されるため、ページが読み込まれるたびに1回取得する必要があります。

私はここで間違った方向に考えているだけなのでしょうか、それともWordPress内でこれがどのように可能になるでしょうか。私は本当にトラフィックの多い本番環境で実行する必要がありますここで良い長期的なソリューションが必要です。ご協力ありがとうございます

4
Daniel

よくわかっていれば、Wordpressのインストールでログインからユーザーのログアウトまで、別のRESTサービスから取得した値をキャッシュする必要があるので、このwp_loginにフックして値とキャッシュを取得します。 トランジェントAPIオプションAPI または 永続キャッシング プラグイン。

add_action('wp_login', 'my_get_and_cache_rest_value');
function my_get_and_cache_rest_value ($user_login, $user) {
    // do your rest call
    // cache it using Transient API, Options API or a persistent caching plugin
}

それからWP_Userオブジェクトを拡張して、必要なデータをキャッシュから取得するためのマジックコールを設定できます。

class MY_User extends WP_User {
    // no constructor so WP_User's constructor is used

    // method to get cached data
    function getMyCachedData() {
        // get data via my cache solution
        if ( ! isset( $this->data->myData ) )
            $this->data->myData = my_get_cached_data( $this->ID );

        return $this->data->myData;
    }

    // magic method to detect $user->my_data
    function __get( $key ) {
        if ( $key == 'my_data' )
        {
            return $this->getMyCachedData();
        }
        else
        {
            // fallback to default WP_User magic method
            return parent::__get( $key );
        }
    }    
}

これが誰かに役立つことを願い、@ Danielに応援します。

1
JBoulhous

以下は質問全体に答えるものではありませんが、それはこの部分に対処します:

@ダニエル:$current_userグローバル変数...は、私の理解する限り、アプリケーション全体を通して利用可能です。私が本当に欲しいのは、アプリケーション全体で同じ可用性があることです。

私も同様のニーズを抱えていましたが、これが私が思いついたことです。

set_current_userフック( wp_set_current_user() 関数内)があり、アクションが起動されるまでに$current_userグローバル変数はWP_Userのインスタンスに設定されるため、このフックを使用して「操作を実行する」ことができます。それ。

wp_get_current_user() を呼び出すと、基本的にグローバルな$current_userの値が返されますが、特定の条件下ではwp_set_current_user()を呼び出すことになり、カスタムアクションが起動する可能性があります。

だから、カスタムプラグイン(これはtheme function.phpファイルではうまくいくとは思わない)で、アクションを定義することができます。

add_action( 'set_current_user', 'extend_current_user', PHP_INT_MAX );

そして、あなたの行動はグローバルな$current_userを上書きすることができます:

public function extend_current_user()
{
    global $current_user;

    if( $current_user->ID == 0 )
        return;

    $current_user = new Student( $current_user->ID );
}

その後、あなたのStudentクラスは Transient API を使用してRESTfulデータをキャッシュし、そのデータを公開するメソッドまたはプロパティを提供できます。そして、グローバルな$current_userはStudentのインスタンスとして残るので、それらが必要なときはいつでもそれらのメソッド/プロパティは常にwp_get_current_user()から利用可能です。

もちろん、こうすることで、 防御的なプログラマー は、wp_get_current_user()への呼び出しがメソッドを呼び出す前にStudentのインスタンスを返すことを確認したいでしょう。

0
Matthew Clark

あなたの質問は少し広いですが、主な問題はあなたが外部のAPIにアプローチしたいすべての新入生のために一度だけであるようです。

これを行うには、 wp_insert_user にフックする必要があります。これは、新しいユーザーを登録するコア機能です。定義上、この関数は新しいユーザーごとに一度だけ呼び出されます。この関数の最後にフック user_register があります。これはAPIにアプローチできる場所です。

add_action ('user_register','wpse185731_approach_api');
function wpse185731_approach_api ($user_id) {
  $userdata = get_userdata( $user_id );
  if ( some condition based on $userdata) {
    ... approach API with $userdata, then store with:
    add_user_meta( $user_id, $meta_key, $meta_value, $unique );
    }
  }

あなたはおそらくあなたのテーマではなく、プラグインでこれをしたいと思うでしょう。

0
cjbj