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

时间:2017-05-02 14:43:19

标签: php wordpress override

我正在尝试覆盖WordPress插件上的插件类。 这是原始的插件类:

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
        }
 }

这是我正在尝试的(在functions.php中),但它不起作用:

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

如何正确删除它以及如何创建替换?

其他信息: 我在WooCommerce核心上做了类似的事情。当我想覆盖一个类/函数时,我使用它(例如):

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' );

它在WooCommerce核心上正常运行。我在WCV_Vendor_Dashboard上尝试了类似的东西,但它不起作用。

1 个答案:

答案 0 :(得分:0)

为什么它与woocommerce合作,但在这种情况下不起作用?

当您将函数附加到特定操作时,WoredPress会为该回调创建唯一ID,并将其存储在全局$wp_filter数组中(事实上,它之前是一个数组,但现在它是一个对象)。对于对象方法回调(如array( $this, 'save_vendor_settings' )),使用spl_object_hash php函数生成id。对于上面的例子,

spl_object_hash( $this ) . 'save_vendor_settings'

,看起来像000000001c0af63f000000006d7fe83asave_vendor_settings

到法律上"使用remove_action()删除对象方法,您将需要访问用于首先附加函数的原始对象。如果对象存在于全局命名空间中:

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

创建另一个类实例将不起作用,因为生成的id对于每个对象都是唯一的,即使它们是同一个类的实例。

在WooCommerce的情况下,我猜它是关于静态类方法。不同的逻辑用于生成静态类方法的id,函数和静态方法回调只是作为字符串返回。对于你的例子,它将是:

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

你知道为什么它适用于一个案例,但不适用于另一个案例。

通过直接在全局$wp_filter对象中替换它们来替换附加的函数是一种破解,但它不是100%可靠的。由于我们无法访问原始对象,因此我们只能通过函数名称过滤$wp_filter,如果相同操作的名称相同,则会替换错误的处理程序。

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';
        }
    }
}

我希望它会起作用,问候。