So entfernen Sie Action-Hooking nicht statische Methoden und Klassen können nicht instanziiert werden

Lesezeit: 9 Minuten

Benutzer-Avatar
Prafulla Kumar Sahu

Ich verwende das Plugin für Woocommerce-Produktanbieter und auf einer einzelnen Produktseite wird es von verkauft. Ich möchte dies ersetzen durch ;

Es wird wie hinzugefügt

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

Ich habe versucht, es wie auszuhaken

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

Konnte diese aber nicht entfernen! Bitte führen Sie mich dazu.

Aktualisieren

Ich habe eine Ausgabe für

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

Benutzer-Avatar
Hallo von Tonya

Warum funktionieren die Lösungen bei Ihnen nicht?

Um einen Callback abzumelden, müssen Sie die Instanz des Objekts abrufen. Das Problem mit diesem Plugin ist: Es verwendet ein Singleton nicht richtig, indem es Ihnen die Möglichkeit gibt, die Instanz zu erfassen. Daher können Sie die Instanz nicht abrufen. Buh.

Arbeiten Sie herum

Wir brauchen eine Problemumgehung. Lassen Sie mich erklären, um Ihnen in Zukunft zu helfen.

WordPress Core speichert alle registrierten Rückrufe in der Registrierung ihrer Ereignisse. Wenn Sie das tun add_action oder add_filter, wird der Rückruf in dieser Ereignisregistrierungstabelle gespeichert (bei der es sich um ein großes mehrdimensionales Array handelt). Um einen Callback abzumelden (oder zu entfernen), der eine Methode innerhalb eines bestimmten Objekts ist (und keine statische Methode), müssen Sie die Instanz des Objekts haben. Das bedeutet, dass Sie die Variable benötigen, die das Objekt darstellt, auf das Sie abzielen möchten.

Hier in diesem Beispiel haben Sie das nicht direkt. Aber WordPress speichert den Schlüssel zur Methode unter Verwendung seiner Objekt-Hash-ID, die mit dem Methodennamen verkettet ist. Dieses Muster können wir verwenden, um den Datensatz (das Element) in der Ereignisregistrierungstabelle abzurufen.

/**
 * #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;
        }
    }
}

Im Wesentlichen macht dieser Code Folgendes:

  1. Überprüft, ob bereits etwas für den Ereignisnamen und die Prioritätsnummer registriert ist. Wenn nein, gibt es nichts zu tun. Lass uns aussteigen.
  2. Wir müssen die eindeutige ID erhalten, oder wie WordPress es nennt, die $idx. Dies ist der eindeutige Schlüssel des Rückrufs, der sich aus der Hash-ID zusammensetzt. Methodenname.
  3. Sobald wir diese eindeutige ID haben, können Sie den Rückruf mit abmelden remove_action. Es funktioniert für remove_filter zu.

Wiederverwendbarer Code

Der obige Code sollte veranschaulichen, wie es geht und wie es funktioniert. Dieser Code ist jedoch nicht wiederverwendbar, da die Parameter fest codiert sind. Stattdessen möchten Sie verwenden dieser Code und dann so aufrufen (wenn in einem Plugin):

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

Welches Event?

Wenn Sie diesen Code in einem Plugin verwenden (was Sie sein sollten), verwenden Sie plugins_loaded.

Wenn Sie es in Ihr Thema einfügen, können Sie es nicht verwenden plugins_loaded weil es bereits ausgelöst wurde, bevor das Thema geladen wurde. Für ein Thema müssen Sie verwenden after_setup_theme Anstatt von plugins_loaded.

Zu testen

Lassen Sie uns zum Testen die Registrierung vorher und nachher ausgeben, um zu sehen, ob sie entfernt wurde. Mach Folgendes:

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] );
    }
}

Die Ergebnisse werden uns zeigen, ob es zu Beginn da war und danach gegangen ist.

  • Du hattest dir wirklich große Mühe gegeben, vielen Dank dafür, aber selbst damit konnte ich das nicht aus dem Ruder machen !!!

    – Prafulla Kumar Sahu

    25. November 2016 um 5:37 Uhr

  • @PrafullaKumarSahu An dieser Stelle müssen Sie das Warum in Ihrem Code debuggen. Verwenden Sie XDebug und/oder var_dump eintippen und sehen was passiert. Ich würde vorschlagen, dass Sie sich die ansehen var_dump( $wp_filter ); Vor dem foreach Schleife und dann danach remove_action läuft. Wenn Sie dort beginnen, sehen Sie, was die eindeutige ID für die Methode ist. Es validiert für Sie auch das Timing von allem, was bedeutet, dass der Callback in diesem Plugin wie erwartet registriert wird. Sie können die Ergebnisse hier posten und wir können Ihnen dabei helfen, den Entdeckungsprozess zu durchlaufen.

    – Hallo von Tonya

    25. November 2016 um 5:44 Uhr

  • Ich habe gerade die Ausgabe für hinzugefügt print_r($wp_filter['woocommerce_single_product_summary']); in meiner frage.

    – Prafulla Kumar Sahu

    25. November 2016 um 5:49 Uhr

  • @PrafullaKumarSahu Ist das nach dem remove_filter() Codezeile oder davor? Wir wollen es vorher und nachher sehen. Wieso den? Before zeigt uns, dass es registriert ist. After zeigt uns, ob es nicht registriert ist.

    – Hallo von Tonya

    25. November 2016 um 5:54 Uhr

  • Ich habe das herausgebracht, indem ich es aufgedruckt habe woocommerce_before_single_product Haken .

    – Prafulla Kumar Sahu

    25. November 2016 um 5:58 Uhr

Benutzer-Avatar
Andy Tschiersch

Versuche dies:

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

Alle Hook-Funktionen für diesen Filter anzeigen:

add_action( 'woocommerce_before_single_product', 'lets_have_a_look' );
function lets_have_a_look(){        
    global $wp_filter;
    print_r($wp_filter['woocommerce_single_product_summary']);
}

  • Vielen Dank für deine Mühe, aber es hat nicht funktioniert 🙁

    – Prafulla Kumar Sahu

    24. November 2016 um 14:34 Uhr

  • Vielleicht hilft es, wenn Sie diesem Filter alle angeschlossenen Funktionen anzeigen. Siehe meine aktualisierte Antwort.

    – Andy Tschiersch

    24. November 2016 um 14:43 Uhr

  • Yeh, Ihre Bemühungen sind hilfreich, lieber Freund. 🙂

    – Prafulla Kumar Sahu

    25. November 2016 um 7:00 Uhr

  • Und viel Liebe und Segen für Ihr süßes Kind. 🙂 <3

    – Prafulla Kumar Sahu

    25. November 2016 um 7:13 Uhr

Oder Sie können es einfach per Javascript tun.

add_action( 'woocommerce_archive_description', "move_author_summary_to_image");
/**
 * Move the author summary right after the image so we can float them left and right.
 */
function move_author_summary_to_image() {
?>
    <script>
    $('document').ready (function () {
        var summary = $("#isle_body .wcpv-vendor-profile.entry-summary").html();
        $("#isle_body .wcpv-vendor-profile.entry-summary").hide();
        $(summary).addClass("author_summary").insertAfter($("#isle_body p.wcpv-vendor-logo")); 

    });
    </script>
<?php
}

1300860cookie-checkSo entfernen Sie Action-Hooking nicht statische Methoden und Klassen können nicht instanziiert werden

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy