add_action referencia uma classe

31

É possível referenciar uma classe em vez de uma função em 'add_action'? Não consigo descobrir. Aqui está apenas um exemplo básico da função em questão.

add_action( 'admin_init', 'MyClass' );
class MyClass {
     function __construct() {
          .. This is where stuff gets done ..
     }
}

Então, sim, isso não funciona. Eu também tentei:

$var = new MyClass();
add_action( 'admin_init', array( &$var ) );

E:

$var = new MyClass();
add_action( 'admin_init', array( &$var, '__construct' ) );

E também:

add_action( 'admin_init', 'MyClass::__construct' );

Existe alguma maneira que eu possa fazer isso sem ter que criar uma função separada que carrega a classe? Eu gostaria de poder apenas executar o construtor de classes através do add_action. Isso é tudo o que precisa ser carregado para fazer a bola rolar.

    
por Matthew Ruddy 05.04.2012 / 15:44
fonte

7 respostas

56

Não, você não pode "inicializar" ou instanciar a turma por meio de um gancho, não diretamente. Algum código adicional é sempre necessário (e não é uma coisa desejável ser capaz de fazer isso, já que você está abrindo uma lata de worms para você mesmo.

Aqui está uma maneira melhor de fazer isso:

class MyClass {
     function __construct() {
          add_action( 'admin_init',array( $this, 'getStuffDone' ) );
     }
     function getStuffDone() {
          // .. This is where stuff gets done ..
     }
}
$var = new MyClass();

É claro que é possível criar uma classe de interface para simplificar ainda mais o caso geral:

class IGetStuffDone {
    function IGetStuffDone(){
        add_action( 'admin_init',array( $this, 'getStuffDone' ) );
    }
    public abstract function getStuffDone();
}

Observe que, como uma interface, você não pode criar um objeto desse tipo diretamente, mas pode criar uma subclasse, permitindo que você diga:

class CDoingThings extends IGetStuffDone {
    function getStuffDone(){
        // doing things
    }
}
$var = new CDoingThings();

O que então adicionaria automaticamente todos os ganchos, você só precisa definir o que exatamente está sendo feito em uma subclasse e depois criá-lo!

Em construtores

Eu não adicionaria um construtor como uma função hook, é uma prática ruim e pode causar muitos eventos incomuns. Além disso, na maioria das linguagens, um construtor retorna o objeto que está sendo instanciado, portanto, se o gancho precisar retornar algo como em um filtro, ele não retornará a variável filtrada como você deseja, mas retornará o objeto de classe.

Chamar um construtor ou um destruidor é uma prática de programação muito, muito, muito ruim, não importa em qual idioma você está, e deve nunca ser feito.

Os construtores também devem construir objetos, para inicializá-los prontos para uso, não para trabalho real. O trabalho a ser feito pelo objeto deve estar em uma função separada.

Métodos de classe estática e sem necessidade de instanciar / inicializar

Se o seu método de classe for um método de classe estático, você poderá passar o nome da classe entre aspas, em vez de $this , conforme mostrado abaixo:

class MyClass {
     public static function getStuffDone() {
          // .. This is where stuff gets done ..
     }
}
add_action( 'admin_init', array('MyClass','getStuffDone' ) );

Closures & PHP 5.3

Infelizmente, você não pode evitar a linha criando a nova classe. A única outra solução para pulá-lo envolveria o código da placa do boiler que ainda tem essa linha e exigiria o PHP 5.3 +, por exemplo:

add_action('admin_init',function(){
    $var = new MyClass();
    $var->getStuffDone();
});

Nesse ponto, você pode pular a turma e usar apenas uma função:

add_action('admin_init',function(){
    // do stuff
});

Mas tenha em mente que você introduziu agora o espectro de funções anônimas. Não há como remover a ação acima usando remove_action , e isso pode causar uma grande dor aos desenvolvedores que precisam trabalhar com o código de outras pessoas.

No e comercial

Você pode ver ações usadas assim:

add_action( &$this, 'getStuffDone' );

Isso é ruim . & foi adicionado de volta no PHP 4 quando os objetos foram passados como valores, não como referências. O PHP 4 tem mais de uma década e não é suportado pelo WordPress há muito tempo.

Não há razão nenhuma para usar &this ao adicionar ganchos e filtros, e remover a referência não causará problemas e pode até melhorar a compatibilidade com versões futuras do PHP

Use isso:

add_action( $this, 'getStuffDone' );
    
por Tom J Nowell 05.04.2012 / 16:16
fonte
9

Exemplo de classe

Notas:

  • Inicia a turma apenas uma vez
    • Chame a prioridade 0, para que você possa usar o mesmo gancho com a prioridade padrão mais tarde
    • Envolva-o em ! class_exists para evitar chamá-lo duas vezes e colocar o chamador de init dentro
  • Crie a função init e a classe var static
  • Chame o construtor de dentro do seu init, quando você chamar a classe new self .

Veja um exemplo

if ( ! class_exists( 'WPSESampleClass' ) )
{
    // Init the class on priority 0 to avoid adding priority inside the class as default = 10
    add_action( 'init', array ( 'WPSESampleClass', 'init' ), 0 );

class WPSESampleClass
{
    /**
     * The Class Object
     */
    static private $class = null;

    public static function init()
    {
        if ( null === self::$class ) 
            self :: $class = new self;

        return self :: $class;
    }

    public function __construct()
    {
        // do stuff like add action calls:
        add_action( 'init', array( $this, 'cb_fn_name' ) );
    }

    public function cb_fn_name()
    {
        // do stuff 
    }
} // END Class WPSESampleClass

} // endif;

Php 5 +

Por favor , deixe o & out. Nós já estamos além do php4. :)

    
por kaiser 05.04.2012 / 16:16
fonte
1
if (!class_exists("AllInOneWoo")){
    class AllInOneWoo {
        function __construct(){
            add_action('admin_menu', array($this, 'all_in_one_woo') );
        }
        function all_in_one_woo(){
            $page_title = 'All In One Woo';
            $menu_title = 'All In One Woo';
            $capability = 'manage_options';
            $menu_slug  = 'all-in-one-woo-menu';
            $function   = array($this, 'all_in_one_woo_menu');
            $icon_url   = 'dashicons-media-code';
            $position   = 59;

            add_menu_page($page_title, $menu_title, $capability, $menu_slug, $function, $icon_url, $position);
        }
        function all_in_one_woo_menu(){?>
            <div class="wrap">
                <h1><?php _e('All In One Woo', 'all_in_one_woo'); ?></h1>
            </div>
        <?php }
    }// end class
}// end if

if (class_exists("AllInOneWoo")){       
    $all_in_one_woo = new AllInOneWoo();
}
    
por Zakir Sajib 04.03.2018 / 09:14
fonte
0

Você pode acionar eventos em sua turma sem a necessidade de carregá-lo inicialmente . Isso é útil se você não quiser carregar a classe completa na frente, mas precisa acessar os filtros e ações do WordPress.

Aqui está um exemplo muito simples

<?php
class MyClass
{
    public static function init()
    {
        add_filter( 'the_content', array('MyClass', 'myMethod') );
    }

    public static function myMethod($content)
    {
        $content = $content . 'Working without loading the object';
    }
}

MyClass::init();

Esta é uma versão muito simplificada da resposta do Kaiser, mas mostra em termos simples o comportamento. Pode ser útil para quem olha para este estilo pela primeira vez.

Outros métodos ainda podem iniciar o objeto, se necessário. Eu estou pessoalmente usando este método para permitir que partes opcionais do meu plugin enfileirem scripts, mas apenas acionando o objeto em uma requisição AJAX.

    
por John Reid 22.12.2014 / 15:02
fonte
0

Isso funciona para mim:

class foo
{
    public static function bar()
    {
        echo 'it works!';
    }
}

add_action('foo_bar', array('foo', 'bar'));
    
por Jonathan 17.03.2015 / 19:25
fonte
0

Em geral, você não adicionaria uma classe inteira a um gancho. Os ganchos add_action() / add_filter() esperam retorno de chamada funções , que podem ser referenciados em dentro de uma classe .

Digamos que você tenha uma função init() dentro de sua classe, que deseja conectar ao gancho init do WordPress.

Coloque sua add_action() call dentro da sua turma e identifique o retorno de chamada assim:

add_action( 'init', array( $this, 'init' ) );

(Nota: suponho que sua classe esteja apropriadamente com namespaces; caso contrário, certifique-se de nomear as funções de retorno de chamada.)

    
por Chip Bennett 05.04.2012 / 16:03
fonte
0

Você deve conseguir passar o nome da turma em vez do objeto instanciado:

add_action( 'init', array( 'MyClass', '__construct' ) );

(Em teoria, sua outra solução deve funcionar também

$var = new MyClass();
add_action( 'admin_init', array( $var, '__construct' ) );

Não tem certeza da cabeça porque não. Talvez se você não ligar por referência?)

    
por Boone Gorges 05.04.2012 / 16:09
fonte

Tags