问题描述
在我的 functions.php
文件中,我想删除下面的过滤器,但我不知道如何做,因为它在一个类中。 remove_filter()
应该是什么样的?
add_filter('comments_array',array( &$this, 'FbComments' ));
它在线 88 here 。
最佳解决方案
这是一个很好的问题。它下降到插件 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()
。
如果我们在 $GLOBALS['wp_filter'][ 'wp_footer' ]
上运行 var_export()
,我们现在可以得到这样的东西:
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'
);
}
Conclusion
- 始终写可预见的代码。为您的过滤器和操作设置可读名称。使其轻松删除任何钩子。
- 以可预测的方式创建对象,例如
'plugins_loaded'
。不只是当您的插件被 WordPress 调用时。
参考文献
注:本文内容整合自 Google/Baidu/Bing 辅助翻译的英文资料结果。如果您对结果不满意,可以加入我们改善翻译效果:薇晓朵技术论坛。