删除通过匿名函数添加的操作/过滤器


10

我必须说,这是一种非常糟糕的坏习惯。最近两个小时用了一个解决方案,以删除通过匿名函数添加的操作和过滤器。

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

/**
 * 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我正在测试它,到目前为止它运行良好。
雷南·奥利维拉

Answers:


10

问题是您无法区分一个匿名函数和另一个匿名函数,是的,可以删除闭包(即匿名函数),但是如果多个闭包以相同的优先级作用于同一过滤器,则必须做出选择,将其全部删除,或者仅删除一个(不确切知道哪个)。

我将展示如何使用从您发布的@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

@adamj自4.7版以来,WordPress引入了处理钩子的新方法,因此不再
可用

您是否有其他选择?
adamj

1
@adamj我可以将其更新为4.7+,但现在没有时间,并且不确定何时才能使用。可以打开一个新问题,将您链接到此Q / A并说这已过时,这样任何人都可以回答,因此,如果我没有时间,也许其他人也可以。作为替代,您可以在这个Q上悬赏,解释说,最受支持的答案在当前版本的WP中
不起作用

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(){} );

通常,这将回到最佳做法。我只会将匿名函数用作我为客户端开发的自定义主题的一部分,在该主题中,我不希望覆盖或删除过滤器。在我开发的任何公共主题或插件中,我都将使用工厂来初始化类,添加所有过滤器和操作,然后将实例存储为静态变量。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.