wordpress - 如何删除action hooking非静态方法和类无法实例化

标签 wordpress woocommerce hook-woocommerce

我正在使用 woocommerce 产品供应商插件,并且在单个产品页面中由 出售。我想用 ;

替换它

添加方式如下

class WC_Product_Vendors_Vendor_Frontend {
    public static function init() {
        $self = new self();

        add_action( 'woocommerce_single_product_summary', array( $self, 'add_sold_by_single' ), 39 );
   return true;
   }
   public function add_sold_by_cart( $values, $cart_item ) {
        $sold_by = get_option( 'wcpv_vendor_settings_display_show_by', 'yes' );

        if ( 'yes' === $sold_by ) {

            $sold_by = WC_Product_Vendors_Utils::get_sold_by_link( $cart_item['data']->id );

            $values[] = array(
                'name' => apply_filters( 'wcpv_sold_by_text', esc_html__( 'Sold By', 'woocommerce-product-vendors' ) ),
                'display' => '<em class="wcpv-sold-by-cart"><a href="' . esc_url( $sold_by['link'] ) . '" title="' . esc_attr( $sold_by['name'] ) . '">' . $sold_by['name'] . '</a></em>',
            );
        }

        return $values;
    }
}
WC_Product_Vendors_Vendor_Frontend::init();

我试着把它解开

1)

add_action( 'wp_head', 'my_remove_actions', 39 );
function my_remove_actions(){
    remove_action( 'woocommerce_single_product_summary', array( 'WC_Product_Vendors_Vendor_Frontend', 'add_sold_by_single' ), 39 );
}

2)

 add_action( 'wp_head', 'my_remove_actions', 39 );
function my_remove_actions(){
    global $wc_product_vendors_vendor_frontend;
    $wc_product_vendors_vendor_frontend = new WC_Product_Vendors_Vendor_Frontend();

    remove_action( 'woocommerce_single_product_summary', array( $wc_product_vendors_vendor_frontend, 'add_sold_by_single' ), 39 );

}

3)

class XWC_Product_Vendors_Vendor_Frontend extends WC_Product_Vendors_Vendor_Frontend{
    public function __construct(){}
}

add_action( 'wp_head', 'my_remove_actions', 39 );
function my_remove_actions(){
    global $xwc_product_vendors_vendor_frontend;
    $xwc_product_vendors_vendor_frontend = new XWC_Product_Vendors_Vendor_Frontend();
    remove_action( 'woocommerce_single_product_summary', array( $xwc_product_vendors_vendor_frontend, 'add_sold_by_single' ), 39 );

}

4)

class XWC_Product_Vendors_Vendor_Frontend extends WC_Product_Vendors_Vendor_Frontend{
        public function __construct() {
    remove_action( 'woocommerce_single_product_summary', array( $this, 'add_sold_by_single' ), 39 );

    }
}
new XWC_Product_Vendors_Vendor_Frontend();

5)

class XWC_Product_Vendors_Vendor_Frontend extends WC_Product_Vendors_Vendor_Frontend{
            public static function init() {
            $self = new self();
        remove_action( 'woocommerce_single_product_summary', array( $self, 'add_sold_by_single' ), 39 );

        }
    }
XWC_Product_Vendors_Vendor_Frontend::init();

但无法删除这个!请指导我这样做。

更新

我得到了输出

print_r($wp_filter['woocommerce_single_product_summary']);

Array
(
    [10] => Array
        (
            [woocommerce_template_single_price] => Array
                (
                    [function] => woocommerce_template_single_price
                    [accepted_args] => 1
                )
        )

    [20] => Array
        (
            [woocommerce_template_single_excerpt] => Array
                (
                    [function] => woocommerce_template_single_excerpt
                    [accepted_args] => 1
                )
        )

    [40] => Array
        (
            [woocommerce_template_single_meta] => Array
                (
                    [function] => woocommerce_template_single_meta
                    [accepted_args] => 1
                )
        )

    [50] => Array
        (
            [woocommerce_template_single_sharing] => Array
                (
                    [function] => woocommerce_template_single_sharing
                    [accepted_args] => 1
                )
        )

    [30] => Array
        (
            [woocommerce_template_single_add_to_cart] => Array
                (
                    [function] => woocommerce_template_single_add_to_cart
                    [accepted_args] => 1
                )
        )

    [39] => Array
        (
            [00000000262d19ef000000007f4708faadd_sold_by_single] => Array
                (
                    [function] => Array
                        (
                            [0] => WC_Product_Vendors_Vendor_Frontend Object
                                (
                                )

                            [1] => add_sold_by_single
                        )

                    [accepted_args] => 1
                )

            [le_child_add_sold_by_single] => Array
                (
                    [function] => le_child_add_sold_by_single
                    [accepted_args] => 1
                )
        )
)

最佳答案

为什么这些解决方案对您不起作用?

为了取消注册回调,您必须获取该对象的实例。这个插件的问题是:它没有为您提供获取实例的方法来正确使用单例。因此,您无法获取该实例。嘘。

解决办法

我们需要一个解决方法。让我解释一下,以便将来对您有所帮助。

WordPress Core 将所有已注册的回调与其事件注册表一起存储。当您执行 add_actionadd_filter 时,回调将存储在此事件注册表(这是一个大型多维数组)中。为了取消注册(或删除)作为特定对象中的方法(而不是静态方法)的回调,您必须拥有该对象的实例。这意味着您需要代表您想要定位的对象的变量。

在此示例中,您没有直接获得它。但是 WordPress 使用对象哈希 ID 与方法名称连接来存储方法的 key 。我们可以使用该模式来获取事件注册表中的记录(元素)。

/**
 * #EXPLANATION#
 * The plugin loads the file using `plugins_loaded` with a priority of 0.  Here
 * we are doing the same thing but after the file is loaded, meaning after the
 * events are registered.
 */

add_action( 'plugins_loaded', 'remove_woocommerce_add_sold_by_single_callback', 1 );
/**
 * Unregister the WooCommerce `WC_Product_Vendors_Vendor_Frontend::add_sold_by_single` from the
 * event `woocommerce_single_product_summary`.
 *
 * #EXPLANATION#
 * I'm adding comments in the code only to illustrate what is happening and why.  Please
 * remove the inline comments when using this code. Thank you.
 *
 * @since 1.0.0
 *
 * @return void
 */
function remove_woocommerce_add_sold_by_single_callback() {
    /**
     * #EXPLANATION#
     * WordPress keeps an event registry table for the callbacks that
     * are pre-registered to each event name.  The format of the table is:
     *
     * $wp_filter[ event name ][ priority number ][ callback name ]
     *
     * The registry table is a global variable called $wp_filter.  You need to include
     * that global into this function's scope.
     */
    global $wp_filter;

    /**
     * #EXPLANATION#
     * Let's make sure that the event name has a callback registered to the priority
     * number of 39. If no, then return early (bail out).
     */
    if ( ! isset( $wp_filter['woocommerce_single_product_summary']['39'] ) ) {
        return;
    }

    /**
     * #EXPLANATION#
     * We will loop through each of the registered callbacks for the priority of 39. Why?
     * You can't assume that only that one function is registered at 39.  There may be more.
     * Therefore, let's loop.
     *
     * We are grabbing the callback function that is registered.  This is a unique key. For
     * objects, WordPress uses the PHP construct spl_object_hash() to grab its hash ID. Then it
     * concatenates it together with the method's name.  You are not going to know what the unique
     * ID is. Why? The first 32 characters are the hash ID, which is a memory location and not
     * relative to the human readable name of `WC_Product_Vendors_Vendor_Frontend`.  Rather, it's
     * related to its object.
     */
    foreach( $wp_filter['woocommerce_single_product_summary']['39'] as $callback_function => $registration ) {
        /**
         * #EXPLANATION#
         * Give that we don't know what the first 32 characters of the object's hash ID is, we need
         * to check if the callback function includes the method we are looking for.  This line
         * of code says: "Hey, do you contain the method name `add_sold_by_single` starting at
         * the 32's character."  If yes, then this is the one we want.
         */
        if ( strpos( $callback_function, 'add_sold_by_single', 32) !== false) {

            /**
             * #EXPLANATION#
             * Now we have the actual callback function key that is registered in the
             * event registry.  We can use remove_action to unregister it.
             */
            remove_action( 'woocommerce_single_product_summary', $callback_function, 39 );

            break;
        }
    }
}

这段代码的作用基本上是这样的:

  1. 检查事件名称和优先级编号中是否已注册任何内容。如果没有,那就没什么可做的了。让我们摆脱困境吧。
  2. 我们需要获取唯一 ID,或者 WordPress 称之为 $idx。这是回调的唯一键,由哈希 ID 组成。方法名称。
  3. 一旦我们获得了该唯一 ID,您就可以使用 remove_action 取消注册回调。它也适用于 remove_filter

可重用代码

上面的代码是为了说明如何做以及它是如何工作的。但该代码不可重用,因为参数是硬编码的。相反,您将需要使用 this code然后像这样调用它(在插件中时):

add_action( 'plugins_loaded', 'remove_woocommerce_add_sold_by_single_callback', 1 );
/**
 * Unregister the WooCommerce `WC_Product_Vendors_Vendor_Frontend::add_sold_by_single` from the
 * event `woocommerce_single_product_summary`.
 *
 * @since 1.0.0
 *
 * @return void
 */
function remove_woocommerce_add_sold_by_single_callback() {
    do_hard_unregister_object_callback( 'woocommerce_single_product_summary', 39, 'add_sold_by_single');
}

哪个事件?

如果您在插件中使用此代码(您应该如此),请使用 plugins_loaded

如果将其放入主题中,则无法使用 plugins_loaded,因为它在主题加载之前就已触发。对于主题,您需要使用 after_setup_theme 而不是 plugins_loaded

测试

为了测试,让我们转储之前和之后的注册表,看看它是否确实删除了它。执行以下操作:

function remove_woocommerce_add_sold_by_single_callback() {
    global $wp_filter;

    var_dump( $wp_filter['woocommerce_single_product_summary'][39] );

    do_hard_unregister_object_callback( 'woocommerce_single_product_summary', 39, 'add_sold_by_single');

    if ( ! isset( $wp_filter['woocommerce_single_product_summary'][39] ) ) {
        var_dump( $wp_filter['woocommerce_single_product_summary'] );
    } else {
        var_dump( $wp_filter['woocommerce_single_product_summary'][39] );
    }
}

结果将让我们看看它是否已经开始并消失了。

关于wordpress - 如何删除action hooking非静态方法和类无法实例化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40788732/

相关文章:

php - 如何使用 PHP 从 MYSQL 检索值到单选按钮?

javascript - 使用 jQuery 取消 css 属性的导航栏固定顶部

php - 仅允许在 WooCommerce 中选定工作日的时间范围内进行购买

php - 替换 Woocommerce 结帐页面中的 "state"选择字段第一个选项文本

php - WooCommerce 结账后更新用户元字段

wordpress - Beaver Builder 插件模板有时没有响应

PHP + CSS : Output Options Framework Content

php - WooCommerce 结帐单选按钮,根据特定项目小计设置百分比费用

php - WooCommerce:如何在管理产品列表中的产品名称旁边添加产品类型

php - WooCommerce:如何以编程方式将多个产品添加到购物车?