問題描述

我想修改外掛中的一個函式。它在外掛的主檔案中宣告如下:

class WCPGSK_Main {
  ...
  public function wcpgsk_email_after_order_table($order) {
    ...
  }
}

從這裡新增呼叫:

add_action( 'woocommerce_email_after_order_table', array($this, 'wcpgsk_email_after_order_table') );

我想這是可以替換它,如果有訪問在 functions.php 中的類。然後我可以寫這樣的東西:

$wcpgsk = new WCPGSK_Main;

remove_action( 'woocommerce_email_after_order_table', array($wcpgsk, 'wcpgsk_email_after_order_table') );

function customized_wcpgsk_email_after_order_table($order) {
  ...
}
add_action( 'woocommerce_email_after_order_table', array($wcpgsk, 'customized_wcpgsk_email_after_order_table') );

我想要在 functions.php 檔案中獲取類的訪問是包含在 functions.php 中宣告類的檔案:

require_once('/wp-content/plugins/woocommerce-poor-guys-swiss-knife/woocommerce-poor-guys-swiss-knife.php');
$wcpgsk = new WCPGSK_Main;
...

但是這並不奏效,因為當外掛在 WordPress 中被初始化時,外掛的檔案被包含在內。

有沒有辦法重寫功能,而不會觸控外掛的檔案?

最佳解決方案

這應該工作:

add_action( 'woocommerce_init', 'remove_wcpgsk_email_order_table' );
function remove_wcpgsk_email_order_table() {

    global $wcpgsk;
    remove_action( 'woocommerce_email_after_order_table', array( $wcpgsk, 'wcpgsk_email_after_order_table' ) );

}

次佳解決方案

如果你的外掛是這樣註冊的:

class Test_Class_Parent {
  function __construct() {
    add_action('wp_head',array($this,'test_method'));
  }

  function test_method() {
    echo 'Echoed from the parent';
  }
}
$p = new Test_Class_Parent();

那麼你應該可以透過訪問全域性來刪除過濾器:

class Test_Class_Child extends Test_Class_Parent {
  function __construct() {
    $this->unregister_parent_hook();
    add_action('wp_head',array($this,'test_method'));
  }

  function unregister_parent_hook() {
    global $p;
    remove_action('wp_head',array($p,'test_method'));
  }

  function test_method() {
    echo 'Echoed from the child';
  }
}
$c = new Test_Class_Child();

否則,您將需要爬行 $wp_filter global 作為註冊碼:

class Test_Class_Child extends Test_Class_Parent {
  function __construct() {
    $this->unregister_parent_hook();
    add_action('wp_head',array($this,'test_method'));
  }

  function unregister_parent_hook() {
    global $wp_filter;
    if (!empty($wp_filter['wp_head'])) {
      foreach($wp_filter['wp_head'] as $cb) {
        foreach ($cb as $k => $v) {
          if (
            isset($v['function'])
            && is_a($v['function'][0],'Test_Class_Parent')
            && isset($v['function'][1])
            && 'test_method' == $v['function'][1]
          ) {
            remove_action('wp_head',$k);
          }
        }
      }
    }
  }

  function test_method() {
    echo 'Echoed from the child';
  }
}
$c = new Test_Class_Child();

這是資源密集型的,除非你沒有其他選擇,否則應該沒有辦法。

參考文獻

注:本文內容整合自 Google/Baidu/Bing 輔助翻譯的英文資料結果。如果您對結果不滿意,可以加入我們改善翻譯效果:薇曉朵技術論壇。