回答:
それは非常に良い質問です。それは、プラグインAPIとプログラミングのベストプラクティスの中心にあります。
次の答えのために、読みやすいコードで問題を説明するために簡単なプラグインを作成しました。
<?php # -*- coding: utf-8 -*-
/* Plugin Name: Anonymous OOP Action */
if ( ! class_exists( 'Anonymous_Object' ) )
{
/**
* Add some actions with randomized global identifiers.
*/
class Anonymous_Object
{
public function __construct()
{
add_action( 'wp_footer', array ( $this, 'print_message_1' ), 5 );
add_action( 'wp_footer', array ( $this, 'print_message_2' ), 5 );
add_action( 'wp_footer', array ( $this, 'print_message_3' ), 12 );
}
public function print_message_1()
{
print '<p>Kill me!</p>';
}
public function print_message_2()
{
print '<p>Me too!</p>';
}
public function print_message_3()
{
print '<p>Aaaand me!</p>';
}
}
// Good luck finding me!
new Anonymous_Object;
}
これが表示されます:
WordPress にはフィルターの名前が必要です。提供しなかったため、WordPressが呼び出し_wp_filter_build_unique_id()
て作成します。この名前はを使用してspl_object_hash()
いるため、予測できません。
私たちが実行した場合var_export()
に$GLOBALS['wp_filter'][ 'wp_footer' ]
、我々は今、このような何かを得ます:
array (
5 =>
array (
'000000002296220e0000000013735e2bprint_message_1' =>
array (
'function' =>
array (
0 =>
Anonymous_Object::__set_state(array(
)),
1 => 'print_message_1',
),
'accepted_args' => 1,
),
'000000002296220e0000000013735e2bprint_message_2' =>
array (
'function' =>
array (
0 =>
Anonymous_Object::__set_state(array(
)),
1 => 'print_message_2',
),
'accepted_args' => 1,
),
),
12 =>
array (
'000000002296220e0000000013735e2bprint_message_3' =>
array (
'function' =>
array (
0 =>
Anonymous_Object::__set_state(array(
)),
1 => 'print_message_3',
),
'accepted_args' => 1,
),
),
20 =>
array (
'wp_print_footer_scripts' =>
array (
'function' => 'wp_print_footer_scripts',
'accepted_args' => 1,
),
),
1000 =>
array (
'wp_admin_bar_render' =>
array (
'function' => 'wp_admin_bar_render',
'accepted_args' => 1,
),
),
)
邪悪なアクションを見つけて削除するには、フックに関連付けられたフィルター(アクションは非常に単純なフィルターです)を調べて、配列であるか、オブジェクトがクラスのインスタンスであるかを確認する必要があります。次に、実際の識別子が表示されることなく、優先順位を設定してフィルターを削除します。
さて、それを関数に入れましょう:
if ( ! function_exists( 'remove_anonymous_object_filter' ) )
{
/**
* Remove an anonymous object filter.
*
* @param string $tag Hook name.
* @param string $class Class name
* @param string $method Method name
* @return void
*/
function remove_anonymous_object_filter( $tag, $class, $method )
{
$filters = $GLOBALS['wp_filter'][ $tag ];
if ( empty ( $filters ) )
{
return;
}
foreach ( $filters as $priority => $filter )
{
foreach ( $filter as $identifier => $function )
{
if ( is_array( $function)
and is_a( $function['function'][0], $class )
and $method === $function['function'][1]
)
{
remove_filter(
$tag,
array ( $function['function'][0], $method ),
$priority
);
}
}
}
}
}
いつこの関数を呼び出すのですか?元のオブジェクトがいつ作成されたかを確実に知る方法はありません。たぶん前に'plugins_loaded'
?たぶん後で?
オブジェクトが関連付けられているのと同じフックを使用して、非常に早い段階で優先的にジャンプします0
。それが本当に確実な唯一の方法です。メソッドを削除する方法はprint_message_3()
次のとおりです。
add_action( 'wp_footer', 'kill_anonymous_example', 0 );
function kill_anonymous_example()
{
remove_anonymous_object_filter(
'wp_footer',
'Anonymous_Object',
'print_message_3'
);
}
結果:
そして、それはあなたの質問からアクションを削除するはずです(テストされていません):
add_action( 'comments_array', 'kill_FbComments', 0 );
function kill_FbComments()
{
remove_anonymous_object_filter(
'comments_array',
'SEOFacebookComments',
'FbComments'
);
}
'plugins_loaded'
。プラグインがWordPressによって呼び出されたときだけではありません。plugins_loaded
は、呼び出されたときに実際に追加されることを確認できますplugins_loaded
。もちろん、おそらくシングルトンパターンを介して、クラスインスタンスにアクセスできる必要があります。
remove_action()
オブジェクトを知っている限り(そしてPHP 5.2以降を使用している場合-現在の安定したPHPバージョンは5.5、5.4はまだサポートされ、5.3はサポート終了です)、remove_filter()
メソッドで削除することができます。覚えておく必要があるのは、オブジェクト、メソッド名、優先度(使用する場合)だけです。
remove_filter('comment_array', [$this, 'FbComments']);
ただし、コードに少し間違いがあります。PHP 4(!)で必要だっ$this
たアンパサンドを前に付けないでください&
。これにより、フックの処理に問題が生じる可能性があるため、邪魔にならないようにしてください。
add_filter('comments_array', [$this, 'FbComments]));
以上です。
$this
外部(別のプラグイン/テーマ)からはアクセスできません。
&
、あなたから&$this
それはPHP 4のことだ、