donglin6109 2017-05-02 14:43
浏览 65
已采纳

如何使用WordPress插件上的构造函数覆盖类?

I'm trying to override a plugin class on a WordPress plugin. Here is the original plugin class :

class WCV_Vendor_Dashboard
{
       /**
        * __construct()
        */
        function __construct()
        {
            add_shortcode( 'wcv_shop_settings', array( $this, 'display_vendor_settings' ) );
            add_shortcode( 'wcv_vendor_dashboard', array( $this, 'display_vendor_products' ) );

            add_action( 'template_redirect', array( $this, 'check_access' ) );
            add_action( 'init', array( $this, 'save_vendor_settings' ) );
        }

        public function save_vendor_settings(){
               //some codes here
        }
 }

Here is what I'm trying (in functions.php), but it doesn't work :

$wcv_vendor_dashboard = new WCV_Vendor_Dashboard();
global $wcv_vendor_dashboard;
remove_action( 'init', array( $wcv_vendor_dashboard , 'save_vendor_settings' ) );

How to remove it correctly and how to create the replacement?

Additional info: I did similar thing on the WooCommerce core. When I want to override a class / function, I use this (for example):

remove_action( 'template_redirect', array( 'WC_Form_Handler', 'save_account_details' ) );
function new_save_account_details() {
  //custom code here
}
add_action( 'template_redirect', 'new_save_account_details' );

It's working properly on WooCommerce core. I tried something similar on WCV_Vendor_Dashboard but it doesn't work.

  • 写回答

2条回答 默认 最新

  • douyun8885 2017-05-02 17:46
    关注

    Why it was working with woocommerce, but it does not work in this case?

    When you attach a function on to a specific action, WoredPress creates unique id for that callback and stores that in global $wp_filter array ( in fact, it was an array before, but now it is an object ). For object method callbacks ( like array( $this, 'save_vendor_settings' ) ), the id is generated with spl_object_hash php function. For the above example,

    spl_object_hash( $this ) . 'save_vendor_settings'
    

    , and it looks like 000000001c0af63f000000006d7fe83asave_vendor_settings.

    To "legally" remove the object method with remove_action() you will need to have access to the original object that was used to attach the function in the first place. If the object exists in global namespace:

    global $wcv;
    remove_action( 'init', array( $wcv, 'save_vendor_settings' ) );
    

    Creating another class instance will not work because the generated id is unique for each object, even if they are instances of the same class.

    In the case of WooCommerce I guess it was about static class methods. Different logic is used to generate the ids for static class methods, functions and static method callbacks are just returned as strings. For your example it would be:

    'WC_Form_Handler' . '::' . 'save_account_details'
    

    You see why it works for one case, but not for the other.

    There is a hack to replace functions attached by replacing them directly in global $wp_filter object, but it's not 100% reliable. Since we do not have access to the original object, we can only filter $wp_filter by the name of the function, if there are identical names for the same action it will replace wrong handlers.

    global $wp_filter;
    foreach ( $wp_filter['init']->callbacks as $priority => &$callbacks ) {
    
        foreach ( $callbacks as $id => &$callback ) {
    
            if ( substr( $id, -strlen( 'save_vendor_settings' ) ) === 'save_vendor_settings' ) {
                // replace the callback with new function
                $callback['function'] = 'new_save_vendor_settings';
            }
        }
    }
    

    I hope it will work, greetings.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?

悬赏问题

  • ¥30 Unity接入微信SDK 无法开启摄像头
  • ¥20 有偿 写代码 要用特定的软件anaconda 里的jvpyter 用python3写
  • ¥20 cad图纸,chx-3六轴码垛机器人
  • ¥15 移动摄像头专网需要解vlan
  • ¥20 access多表提取相同字段数据并合并
  • ¥20 基于MSP430f5529的MPU6050驱动,求出欧拉角
  • ¥20 Java-Oj-桌布的计算
  • ¥15 powerbuilder中的datawindow数据整合到新的DataWindow
  • ¥20 有人知道这种图怎么画吗?
  • ¥15 pyqt6如何引用qrc文件加载里面的的资源