ฉันจะแทนที่ฟังก์ชั่นที่ประกาศในคลาสของปลั๊กอินใน functions.php ได้อย่างไร


9

ฉันต้องการแก้ไขฟังก์ชั่นในปลั๊กอิน มันถูกประกาศในไฟล์หลักของปลั๊กอินดังนี้:

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 ฉันเดา

มีวิธีการเขียนฟังก์ชั่นใหม่โดยไม่ต้องสัมผัสไฟล์ปลั๊กอินหรือไม่?

คำตอบ:


8

สิ่งนี้น่าจะใช้ได้:

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

}


ใช่ฉันไม่ได้รับปลั๊กอินนี้มีตัวแปรที่สามารถเข้าถึงได้ในระดับสากล ความโง่เขลาของฉัน ขอขอบคุณสำหรับคำตอบของคุณการทำงานในกรณีนี้โดยเฉพาะ (สำหรับปลั๊กอินนี้)
Igor Skoldin

Alex Older เชื่อมโยงกับสถานที่ที่อธิบายว่าทำไมคำตอบของเขาจึงใช้ได้ remove_action ยอมรับอาร์เรย์ที่มีคลาสแบบสแตติกหรืออินสแตนซ์ซึ่งคุณต้องการลบเมธอด
ninja08

11

หากปลั๊กอินของคุณลงทะเบียนแบบนี้:

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

นี่เป็นทรัพยากรที่เข้มข้นและไม่ควรทำเว้นแต่คุณจะไม่มีทางเลือกอื่น


2
นี่ควรเป็นคำตอบที่ยอมรับได้ โดยทั่วไปมีประโยชน์มากกว่าและไม่ จำกัด เฉพาะกรณีของ OP เท่านั้น
เดวิดอาร์

1

ปลั๊กอินนั้นทำให้ฟังก์ชั่น init สามารถwcpgsk_init()เสียบได้ดังนั้นอีกวิธีหนึ่งในการแทนที่ก็คือการกำหนดเป็นอันดับแรกในปลั๊กอินที่ต้องใช้ (เพราะมันสายเกินไปในฟังก์ชั่น ดังนั้นคุณสามารถแทนที่ของคุณใน "wp-content / mu-plugins / functions.php":

function wcpgsk_init() {
    global $wcpgsk, $wcpgsk_about, $wcpgsk_options, $wcpgsk_session, $wcpgsk_woocommerce_active;    
    //only continue loading
    if ( $wcpgsk_woocommerce_active && version_compare( WOOCOMMERCE_VERSION, "2.0" ) >= 0 ) {
        $FILE = WP_PLUGIN_DIR . '/woocommerce-poor-guys-swiss-knife/woocommerce-poor-guys-swiss-knife.php'; // Fake __FILE__
        $dirname = dirname( $FILE ) . '/';
        $wcpgsk_options = get_option('wcpgsk_settings', true);
        require_once( $dirname . 'classes/woocommerce-poor-guys-swiss-knife.php' );
        require_once( $dirname . 'classes/woocommerce-poor-guys-swiss-knife-about.php' );   
        require_once( $dirname . 'wcpgsk-af.php' );

        if ( !is_admin() ) :
            add_action( 'plugins_loaded', 'wcpgsk_load_wcsession_helper' );
        endif;

        // Your override.
        class My_WCPGSK_Main extends WCPGSK_Main {
            public function wcpgsk_email_after_order_table($order) {
                echo "O la la";
            }
        }
        define( 'WCRGSK_DOMAIN', WCPGSK_DOMAIN ); // Fix typo! (WooCommerce Rich Guys Swiss Knife?)

        //load into our global
        $wcpgsk = new My_WCPGSK_Main( $FILE );
        $wcpgsk->version = '2.2.4'; 
        $wcpgsk->wcpgsk_hook_woocommerce_filters();


    } elseif ( version_compare( WOOCOMMERCE_VERSION, "2.0" ) < 0 ) {
        add_action( 'admin_notices', 'wcpgsk_woocommerce_version_message', 0 ) ;    
        return;
    } else {
        return;
    }
}

แต่วิธีที่ดีกว่าในการแทนที่คือการติดตั้งrunkit( https://github.com/padraic/runkit ) จากนั้นให้แทนที่โดยตรงใน "functions.php" ของธีมของคุณ:

add_action( 'init', function () {
    $code = <<<'EOD'
echo "O la la";
EOD;
    runkit_method_redefine(
        'WCPGSK_Main',
        'wcpgsk_email_after_order_table',
        '$order',
        $code,
        RUNKIT_ACC_PUBLIC
    );
} );

(นั่นเป็นเรื่องตลก btw.)

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.