匿名関数を介して追加されたアクション/フィルターを削除する


10

それは私が言わなければならないひどく悪い習慣です。匿名機能を介して追加されたアクションとフィルターを削除するソリューションを見つけるために、過去2時間を費やしました。

これは、親テーマで使用されるコードであり、削除する必要があります。

/**
 * Add custom columns to admin comments grid
 *  * Rate that user set.
 */
add_filter( 'manage_edit-comments_columns', function( $default ) {
    $columns['smr_comment_rate']  = __( 'Rate', 'txtdmn' );

    return array_slice( $default, 0, 3, true ) + $columns + array_slice( $default, 2, NULL, true );
});

toschoの答えを得た、それでひどく遊んだ、しかし助けはなかった。それで、匿名関数を介して追加されたアクション/フィルターを削除する他の選択肢はありますか?

ありがとう


テーマの作者に連絡することをお勧めします。匿名の代わりに名前付き関数を使用するのは比較的簡単な修正であり、コードを改善します。
helgatheviking 2014年

gmazzap @ vishalbasnet23がここで実行したように見えます:gist.github.com/vishalbasnet23/5f74df4c800681199ab0246bc037d1d5私はそれをテストしていますが、これまでのところ、完全に動作しています。
Renan Oliveira

回答:


10

問題は、無名関数と別の関数を区別できないことです。そのため、はい、クロージャ(つまり、無名関数)を削除することは可能ですが、複数のクロージャが同じフィルタで同じ優先度で動作する場合は、選択する必要があります。 、それらをすべて削除するか、または1つだけ削除します(正確にどちらがわからない場合でも)。

私はあなたが投稿した@toscho回答の関数から高度に派生した関数を使用してそれらをすべて削除する方法を示します:

/**
 * Remove an object filter.
 *
 * @param  string $tag                Hook name.
 * @param  string $class              Class name. Use 'Closure' for anonymous functions.
 * @param  string|void $method        Method name. Leave empty for anonymous functions.
 * @param  string|int|void $priority  Priority
 * @return void
 */
function remove_object_filter( $tag, $class, $method = NULL, $priority = NULL ) {
  $filters = $GLOBALS['wp_filter'][ $tag ];
  if ( empty ( $filters ) ) {
    return;
  }
  foreach ( $filters as $p => $filter ) {
    if ( ! is_null($priority) && ( (int) $priority !== (int) $p ) ) continue;
    $remove = FALSE;
    foreach ( $filter as $identifier => $function ) {
      $function = $function['function'];
      if (
        is_array( $function )
        && (
          is_a( $function[0], $class )
          || ( is_array( $function ) && $function[0] === $class )
        )
      ) {
        $remove = ( $method && ( $method === $function[1] ) );
      } elseif ( $function instanceof Closure && $class === 'Closure' ) {
        $remove = TRUE;
      }
      if ( $remove ) {
        unset( $GLOBALS['wp_filter'][$tag][$p][$identifier] );
      }
    }
  }
}

remove_object_filterすべてのタイプのオブジェクトフィルター(静的クラスメソッド、動的オブジェクトメソッド、クロージャー)を削除できるため、関数の名前を変更しました。

$priority引数はオプションですが、それは常に使用する必要があるクロージャを取り外すときに、ときので、それ以外の機能は、その優先順位でフィルタに追加された閉鎖、関係なく削除します $priority省略され、ターゲットクラス/メソッドやクロージャを使用して、すべてのフィルタがあります削除されました。

使い方

// remove a static method
remove_object_filter( 'a_filter_hook', 'AClass', 'a_static_method', 10 );

// remove a dynamic method
remove_object_filter( 'a_filter_hook', 'AClass', 'a_dynamic_method', 10 );

// remove a closure
remove_object_filter( 'a_filter_hook', 'Closure', NULL, 10 );

私はこれと他の多くを試しましたが、それは単に機能しません
adamj '7/07/17

@adamjバージョン4.7以降、WordPressはフックを処理する新しい方法を導入したため、これはもう機能しません...
gmazzap

万が一代替案を知っていますか?
adamj 2017

1
@adamj 4.7+でこれを更新することはできましたが、今は時間がないので、いつになるかわかりません。新しい質問を開いて、このQ / Aにリンクして、これが古くなっていると言って、誰でも答えられるようにしてください。時間がなければ、他の誰かが答えるでしょう。別の方法として、このQに賞金をかけることもできます。ここで最も投票された答えは、現在のバージョンのWPでは機能しないことを説明します...
gmazzap

3

優先度11のフィルターを追加するとどうなるでしょうか。それは醜いですが、あなたの場合にはうまくいくかもしれません。

add_filter( 'manage_edit-comments_columns', function( $default ) {
    unset( $default['smr_comment_rate'] );

    return $default;
}, 11, 1 );

2

匿名のフィルターとアクションは、以下を使用してネイティブに削除できます。

remove_filter( $tag, function(){}, $priority )

を使用して一意のIDを生成する場合spl_object_hash()、匿名関数は互いに比較できるため、完全なクロージャーオブジェクトを再作成する必要はありません。

複数のフィルターまたはアクションが同じタグに同じ優先度で接続されている場合、追加された最新のフィルターまたはアクションが削除されます。保持する必要があるものがある場合は、削除する必要があるものまでのすべてのフィルターを削除し、必要に応じて他のフィルターを再度追加する必要があります。

// Filter which was added and needs to be removed
add_filter( 'manage_edit-comments_columns', function( $default ) {
    $columns['smr_comment_rate']  = __( 'Rate', 'txtdmn' );

    return array_slice( $default, 0, 3, true ) + $columns + array_slice( $default, 2, NULL, true );
} );

// Removes the last anonymous filter to be added
remove_filter( 'manage_edit-comments_columns', function(){} );

これは通常、ベストプラクティスに戻ります。匿名関数は、クライアント用に開発しているカスタムテーマの一部としてのみ使用します。フィルターを上書きしたり削除したりする必要はありません。開発するパブリックテーマまたはプラグインでは、ファクトリを使用してクラスを初期化し、すべてのフィルターとアクションを追加して、インスタンスを静的変数として保存します。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.