akcje – usuń_akcję lub usuń_filter z klasami zewnętrznymi?
Ilekroć wtyczka tworzy plik new MyClass();
, powinien przypisać ją do zmiennej o unikatowej nazwie. W ten sposób instancja klasy będzie dostępna.
Więc jeśli to robił $myclass = new MyClass();
możesz to zrobić:
global $myclass;
remove_action( 'wp_footer', array( $myclass, 'my_action' ) );
Działa to, ponieważ wtyczki są zawarte w globalnej przestrzeni nazw, więc ukryte deklaracje zmiennych w głównej części wtyczki są zmiennymi globalnymi.
Jeśli wtyczka nie zapisze identyfikatora nowej klasy gdzieś, więc technicznie rzecz biorąc, jest to błąd. Jedną z ogólnych zasad programowania obiektowego jest to, że obiekty, do których nie odwołuje się żadna zmienna, podlegają czyszczeniu lub eliminacji.
W szczególności PHP nie robi tego tak, jak zrobiłaby to Java, ponieważ PHP jest w pewnym sensie niedopracowaną implementacją OOP. Zmienne instancji to po prostu ciągi znaków z unikalnymi nazwami obiektów. Działają one tylko ze względu na sposób, w jaki interakcja nazwy funkcji zmiennej współpracuje z plikiem ->
operator. Więc po prostu robię new class()
rzeczywiście może działać idealnie, tylko głupio. 🙂
Podsumowując, nigdy tego nie rób new class();
. Do $var = new class();
i udostępnij ten $var w jakiś sposób, aby inne bity mogły się do niego odwoływać.
Edycja: lata później
Jedną z rzeczy, które widziałem w wielu wtyczkach, jest użycie czegoś podobnego do wzorca „Singleton”. Tworzą metodę getInstance(), aby uzyskać pojedynczą instancję klasy. To prawdopodobnie najlepsze rozwiązanie, jakie widziałem. Przykładowa wtyczka:
class ExamplePlugin
{
protected static $instance = NULL;
public static function getInstance() {
NULL === self::$instance and self::$instance = new self;
return self::$instance;
}
}
Przy pierwszym wywołaniu metody getInstance() tworzy ona instancję klasy i zapisuje jej wskaźnik. Możesz tego użyć do podpięcia działań.
Jednym z problemów jest to, że nie możesz użyć funkcji getInstance() wewnątrz konstruktora, jeśli używasz czegoś takiego. Dzieje się tak, ponieważ new wywołuje konstruktor przed ustawieniem $instance, więc wywołanie getInstance() z konstruktora prowadzi do nieskończonej pętli i wszystko psuje.
Jednym z rozwiązań jest nieużywanie konstruktora (lub przynajmniej nie używanie w nim funkcji getInstance()), ale jawne posiadanie w klasie funkcji „init” umożliwiającej konfigurowanie działań itp. Lubię to:
public static function init() {
add_action( 'wp_footer', array( ExamplePlugin::getInstance(), 'my_action' ) );
}
W przypadku czegoś takiego na końcu pliku, po zdefiniowaniu całej klasy, utworzenie instancji wtyczki staje się tak proste, jak to:
ExamplePlugin::init();
Init zaczyna dodawać Twoje akcje i w ten sposób wywołuje metodę getInstance(), która tworzy instancję klasy i upewnia się, że tylko jedna z nich istnieje. Jeśli nie masz funkcji init, możesz to zrobić, aby początkowo utworzyć instancję klasy:
ExamplePlugin::getInstance();
Aby odpowiedzieć na pierwotne pytanie, usunięcie tego haka akcji z zewnątrz (czyli w innej wtyczce) można następnie wykonać w następujący sposób:
remove_action( 'wp_footer', array( ExamplePlugin::getInstance(), 'my_action' ) );
Umieść to w czymś podłączonym do plugins_loaded
hak akcji i cofnie akcję zaczepioną przez oryginalną wtyczkę.