问题描述

这是一个非常糟糕的做法,我必须说。花了两个小时的时间找到一个解决方案来删除通过匿名功能添加的操作和过滤器。

这是父主题上使用的代码,我需要删除它。

/**
 * 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’s answer,玩了很多,但没有帮助。那么还有其他替代方法可以删除通过匿名函数添加的动作/过滤器吗?

谢谢

最佳解决方案

问题是你不能区分形式的匿名函数和另一个,所以是的,可以删除一个闭包 (即匿名函数),但如果多个闭包在同一个过滤器上以同样的优先级行事,你必须做出选择,删除它们,矿石只能移除一个 (不知道哪个) 。

我将展示如何使用从 @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 );

参考文献

注:本文内容整合自 Google/Baidu/Bing 辅助翻译的英文资料结果。如果您对结果不满意,可以加入我们改善翻译效果:薇晓朵技术论坛。