Sempre que um plug-in cria um new MyClass();
, ele deve atribuí-lo a uma variável com nome exclusivo. Dessa forma, a instância da classe é acessível.
Então, se ele estava fazendo $myclass = new MyClass();
, então você poderia fazer o seguinte:
global $myclass;
remove_action( 'wp_footer', array( $myclass, 'my_action' ) );
Isso funciona porque os plug-ins estão incluídos no espaço para nome global, portanto, as declarações implícitas de variáveis no corpo principal de um plug-in são variáveis globais.
Se o plugin não salvar o identificador da nova classe em algum lugar , tecnicamente, isso é um bug. Um dos princípios gerais da Programação Orientada a Objetos é que objetos que não estão sendo referenciados por alguma variável em algum lugar estão sujeitos a limpeza ou eliminação.
Agora, o PHP em particular não faz isso como o Java faria, porque o PHP é meio que uma implementação de OOP meio arsada. As variáveis de instância são apenas strings com nomes de objetos exclusivos, algo assim. Eles funcionam apenas devido à maneira como a interação do nome da função variável funciona com o ->
operador. Então, apenas fazer new class()
pode realmente funcionar perfeitamente, apenas estupidamente. :)
Então, linha de fundo, nunca faça new class();
. Faça $var = new class();
e torne esse $ var acessível de alguma maneira para outros bits fazerem referência a ele.
Edit: anos depois
Uma coisa que eu já vi muitos plugins fazendo é usar algo semelhante ao padrão "Singleton". Eles criam um método getInstance () para obter a única instância da classe. Esta é provavelmente a melhor solução que eu já vi. Exemplo de plug-in:
class ExamplePlugin
{
protected static $instance = NULL;
public static function getInstance() {
NULL === self::$instance and self::$instance = new self;
return self::$instance;
}
}
A primeira vez que getInstance () é chamado, ele instancia a classe e salva seu ponteiro. Você pode usar isso para conectar ações.
Um problema com isso é que você não pode usar getInstance () dentro do construtor se usar isso. Isso ocorre porque o novo chama o construtor antes de definir a instância $, então chamar getInstance () do construtor leva a um loop infinito e quebra tudo.
Uma solução alternativa é não usar o construtor (ou, pelo menos, não usar getInstance () dentro dele), mas ter explicitamente uma função "init" na classe para configurar suas ações e tal. Como isso:
public static function init() {
add_action( 'wp_footer', array( ExamplePlugin::getInstance(), 'my_action' ) );
}
Com algo assim, no final do arquivo, após a classe ter sido definida e tal, a instanciação do plug-in torna-se tão simples quanto isto:
ExamplePlugin::init();
O Init começa a adicionar suas ações e, ao fazer isso, chama getInstance (), que instancia a classe e garante que apenas uma delas exista. Se você não tiver uma função init, faça isso para instanciar a classe inicialmente:
ExamplePlugin::getInstance();
Para resolver a questão original, a remoção desse gancho de ação de fora (também conhecido como outro plugin) pode ser feita da seguinte maneira:
remove_action( 'wp_footer', array( ExamplePlugin::getInstance(), 'my_action' ) );
Coloque isso em algo ligado ao plugins_loaded
gancho de ação e ele desfará a ação que está sendo conectada pelo plug-in original.