Em uma situação em que um plug-in encapsulou seus métodos dentro de uma classe e depois registrou um filtro ou ação contra um desses métodos, como você remove a ação ou o filtro se não tem mais acesso à instância dessa classe?
Por exemplo, suponha que você tenha um plugin que faça isso:
class MyClass {
function __construct() {
add_action( "plugins_loaded", array( $this, 'my_action' ) );
}
function my_action() {
// do stuff...
}
}
new MyClass();
Observando que agora não tenho como acessar a instância, como cancelo o registro da classe? Isso: remove_action( "plugins_loaded", array( MyClass, 'my_action' ) );
não parece ser a abordagem correta - pelo menos, não parecia funcionar no meu caso.
Respostas:
A melhor coisa a fazer aqui é usar uma classe estática. O código a seguir deve ser instrutivo:
Se você executar esse código em um plug-in, observe que o método da StaticClass e a função serão removidos do wp_footer.
fonte
remove_action
função, caso contrário não funcionará ... é por isso que eu tive que escrever minha própria função para lidar quando não é uma classe estática. Essa resposta só seria o melhor se sua pergunta foi sobre o seu próprio código, caso contrário, você estará tentando remover outro filtro / ação de outra pessoa base de código e não pode mudá-lo para estáticoSempre 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: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 fazernew 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:
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:
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:
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:
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:
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.fonte
wp_loaded
, nãoplugins_loaded
, que pode ser chamado muito cedo.plugins_loaded
seria o lugar correto. Awp_loaded
ação acontece após ainit
ação; portanto, se o seu plug-in executa alguma açãoinit
(e a maioria faz), você deseja inicializar o plug-in e configurá-lo antes disso. Oplugins_loaded
gancho é o lugar certo para a fase de construção.2 pequenas funções PHP para permitir a remoção de filtro / ação com a classe "anônimo": https://github.com/herewithme/wp-filters-extras/
fonte
Aqui está uma função amplamente documentada que eu criei para remover filtros quando você não tem acesso ao objeto de classe (funciona com WordPress 1.2+, incluindo 4.7+):
https://gist.github.com/tripflex/c6518efc1753cf2392559866b4bd1a53
fonte
As soluções acima parecem desatualizadas, tive que escrever as minhas ...
fonte
Esta função é baseada na resposta @Digerkam. Adicionado compare if
$def['function'][0]
é string e finalmente funcionou para mim.O uso também
$wp_filter[$tag]->remove_filter()
deve torná-lo mais estável.Exemplo de uso:
Combinação exata
Qualquer prioridade
Qualquer classe e qualquer prioridade
fonte
Esta não é uma resposta genérica, mas uma específica para o tema Avada e o WooCommerce , que acho que outras pessoas podem achar úteis:
fonte