WordPress如何移除第三方插件类内挂载的pre_get_users动作钩子
WordPress移除第三方插件类挂载动作钩子的正确实现方案
问题根源
- 自定义插件的默认加载顺序早于目标第三方插件,触发
plugins_loaded钩子时目标类还未被加载,所以报类未找到错误 - 目标类存储自身实例的静态属性是
$self,你误用了不存在的$instance属性和getInstance()方法,无法正确获取类实例
方案1:直接通过类实例移除(仅适用于目标类$self属性为public的情况)
function remove_wc_product_vendors_filter() { // 先判断目标类是否存在,避免报错 if ( class_exists( 'WC_Product_Vendors_Vendor_Admin' ) ) { // 用原类定义的$self属性获取实例,移除钩子时优先级要和添加时一致(默认10) remove_action( 'pre_get_users', array( WC_Product_Vendors_Vendor_Admin::$self, 'filter_users' ), 10 ); } } // 优先级设为999,确保执行时第三方插件已经完成加载和初始化 add_action( 'plugins_loaded', 'remove_wc_product_vendors_filter', 999 );
如果原类的$self属性是private/protected修饰的非公开属性,直接访问会报错,此时使用通用方案2。
方案2:通过全局钩子注册表移除(通用方案,无需获取类实例)
function remove_wc_product_vendors_filter() { global $wp_filter; $target_hook = 'pre_get_users'; $target_method = 'filter_users'; // 确认目标钩子存在注册的回调 if ( isset( $wp_filter[ $target_hook ]->callbacks ) ) { // 遍历所有优先级的回调 foreach ( $wp_filter[ $target_hook ]->callbacks as $priority => $callbacks ) { foreach ( $callbacks as $callback ) { // 匹配回调为数组格式、且第二个元素为目标方法名 if ( is_array( $callback['function'] ) && $callback['function'][1] === $target_method ) { // 确认回调的对象是目标类的实例 if ( $callback['function'][0] instanceof WC_Product_Vendors_Vendor_Admin ) { remove_action( $target_hook, $callback['function'], $priority ); } } } } } } add_action( 'plugins_loaded', 'remove_wc_product_vendors_filter', 999 );
注意事项
- 不需要更换到
wp_head、init等钩子,只要把plugins_loaded的优先级设为足够大的数值(比如999)就能保证第三方插件先加载完成 remove_action的优先级必须和原add_action的优先级完全一致,否则无法移除,原代码未设置优先级默认是10,所以移除时也要对应使用10的优先级
内容的提问来源于stack exchange,提问作者Josh Regev
相关产品推荐
相关产品推荐

