web-dev-qa-db-ja.com

Current_user_can()および関連関数を使用する有効なタイミングは何ですか?

Vanilla WPコアロードの間、現在のユーザーはテーマロードの後でinitフックの前の$wp-init()にセットアップされています。これはinit以降にフックされる機能の良い習慣と一致しています。

ただし、current_user_can() early などの関連関数を呼び出すのも一般的な方法です。定義上、ロードプロセスの初期段階で動作するプラグインには必須です(私のToolbar Theme Switcherプラグインがその例です)。

ドキュメンテーションは、(私が見つけることができる)この慣行に対して、またはそれに反対する主張をしません。

しかし一部のプラグインはユーザー関連の機能にフックしているようで、常に_ init stateを期待しています。

たとえば、bbPressは次のように通知します。

// If the current user is being setup before the "init" action has fired,
// strange (and difficult to debug) role/capability issues will occur.
if ( ! did_action( 'after_setup_theme' ) ) {
    _doing_it_wrong( __FUNCTION__, __( 'The current user is being initialized without using $wp->init().', 'bbpress' ), '2.3' );
}

簡単にデモンストレーションするために、これをコアのcurrent_user_can()の定義に入れてください。

function current_user_can( $capability ) {

    if ( ! did_action('after_setup_theme') ) {
        echo wp_debug_backtrace_summary();
    }

誰がこの状況で「正しい」ですか? initの前に、ユーザ関連の関数の許可された/禁止された使用法についての正式な決定はありますか?

10
Rarst

current_user_can()の唯一の前提条件は既存のwp_get_current_user()です。後者はpluggable.phpで定義されているので、plugins_loadedの後に使うことができます。

あなたがあなたの質問で引用している_doing_it_wrong()呼び出しはそれ自体が間違っています。私はあなたがBuddyPressまたはbbPressからそれを取ったと思います。彼らがそれほど長く待たなければ、両方とも再帰に遭遇しています。再帰を防ぐための他のより良い方法があります。

ロケールの変更 のように、現在のユーザオブジェクトに早くアクセスするためにhaveを使う場合もあるので、after_setup_themeを待つのも選択肢にはなりません。

7
fuxia

initの前にユーザーの能力をチェックすると、可能性があることを意味しますyouが現在のユーザーオブジェクトの設定を担当します。

ユーザーafterinitにアクセスすると、something elseすでにユーザーをセットアップしています。ほとんどの場合、コアそのものです。

これが、initの後にユーザーにアクセスすることが考慮される理由ですsafe

実際、早期アクセスにより、determine_current_userで実行されている一部のフィルターが破損する可能性があります。

1つは「壊れやすい」フックであると言う価値があります。プラグイン可能な関数でのみ起動されるため、実行されない可能性があるからです。

ただし、(@ toschoのように)あなたができないinitまで待つことができる場合があります。そのような場合、選択の余地はありません。

非互換性を解決する唯一の方法は、必要に応じてケースバイケースです。

mayが機能する解決策は、ほとんどの場合(bbPress/BuddyPressを含む)_current_user_canの代わりに次の関数を使用することです。

function compat_current_user_can( $capability )
{
  if ( did_action( 'init' ) ) {
     return current_user_can( $capability );
  }

  $user_id = apply_filters( 'determine_current_user', false );

  return user_can( $user_id, $capability );
}

これにより、グローバルユーザーを設定せずに現在のユーザー機能を早期に確認できるため、理論上initの前に安全に実行できます。

問題は、前述のように、プラグイン可能な関数をオーバーライドし、determine_current_userを起動しないコードがそれを壊すことです。

2
gmazzap

私はBuddyPressとbbPressが_doing_it_wrongメッセージを出す前に何か他のものをチェックすべきだと思う傾向があります

$ current_userの実際の設定もチェックするように両方のルーチンを変更しました。

global $current_user; 
if ( is_null( $current_user ) ) {
    _doing_it_wrong( ... );
}

通知は表示されなくなりました。

did_action( "after_setup_theme" )のテストはベルトと一緒に行くためのブレースになります。

1
bobbingwide