Erro PHP com manipulador de shortcode de uma classe

13

Atualmente, estou usando o seguinte fluxo genérico para adicionar o código curto para um plug-in.

class MyPlugin {

    private $myvar;

    function baztag_func() {
        print $this->myvar;            
    }
}

add_shortcode( 'baztag', array('MyPlugin', 'baztag_func') );

Agora, quando essa classe e seu método são chamados, recebo o seguinte erro.

Erro fatal: usar $ this quando não estiver no contexto do objeto em ...

(A linha no é onde eu imprimi o $this->myvar)

Isso é um problema no final do Wordpress ou há algo que estou fazendo de errado? Parece ser algo realmente simples.

xmaestro
fonte
off topic - faça a função static.
Kaiser #

Respostas:

31

Como o erro indica, você precisa de uma instância da classe para usar $this . Existem pelo menos três possibilidades:

Tornar tudo estático

class My_Plugin
{
    private static $var = 'foo';

    static function foo()
    {
        return self::$var; // never echo or print in a shortcode!
    }
}
add_shortcode( 'baztag', array( 'My_Plugin', 'foo' ) );

Mas isso não é mais POO real, apenas espaço para nome.

Crie um objeto real primeiro

class My_Plugin
{
    private $var = 'foo';

    public function foo()
    {
        return $this->var; // never echo or print in a shortcode!
    }
}

$My_Plugin = new My_Plugin;

add_shortcode( 'baztag', array( $My_Plugin, 'foo' ) );

Isso funciona. Mas você enfrenta alguns problemas obscuros se alguém quiser substituir o código de acesso.

Portanto, adicione um método para fornecer a instância da classe:

final class My_Plugin
{
    private $var = 'foo';

    public function __construct()
    {
        add_filter( 'get_my_plugin_instance', [ $this, 'get_instance' ] );
    }

    public function get_instance()
    {
        return $this; // return the object
    }

    public function foo()
    {
        return $this->var; // never echo or print in a shortcode!
    }
}

add_shortcode( 'baztag', [ new My_Plugin, 'foo' ] );

Agora, quando alguém deseja obter a instância do objeto, ele apenas precisa escrever:

$shortcode_handler = apply_filters( 'get_my_plugin_instance', NULL );

if ( is_a( $shortcode_handler, 'My_Plugin ' ) )
{
    // do something with that instance.
}

Solução antiga: crie o objeto em sua classe

class My_Plugin
{
    private $var = 'foo';

    protected static $instance = NULL;

    public static function get_instance()
    {
        // create an object
        NULL === self::$instance and self::$instance = new self;

        return self::$instance; // return the object
    }

    public function foo()
    {
        return $this->var; // never echo or print in a shortcode!
    }
}

add_shortcode( 'baztag', array( My_Plugin::get_instance(), 'foo' ) );
fuxia
fonte
thanx man ... são informações de valor inestimável, já que o wordpress.org não contou muito isso na página de documentação do add_shortcode. Eu tinha descoberto a solução, mas desde que você descartou essa possibilidade como uma prática ruim e você tem uma solução melhor para que eu marcar este problema como resolvido :)
xmaestro
Lamento muito desenterrar esta pergunta antiga, mas você poderia explicar o que essa linha faz NULL === self::$instance and self::$instance = new self;:? Estou um pouco confuso porque ===e andusado, mas sem if, se é que você me entende.
Sven
@ Sven Esta é uma verificação para impedir uma segunda instância. Faz dessa classe um Singleton ... Eu não faria isso hoje em dia. Vou reescrever esta resposta.
fuxia
Obrigado por isso! Eu acho que agora estou no caminho certo, embora seja surpreendente o quão complicado pode estar usando WordPress & OOP ;-)
Sven
2
O núcleo do @Sven WordPress é escrito da maneira mais anti-OOP possível. Até o novo código ignora todas as coisas que o resto do mundo PHP aprendeu nos últimos dez anos, por exemplo, injeção de dependência. Então, sim, OOP em plugins e temas do WordPress é sempre hackeado. : /
fuxia
7

Você pode usar assim, shortcode dentro da Classe

class stockData{


    function __construct() {
        add_shortcode( 'your_shortcode_name', array( $this, 'showData' ) );
        //add_action('login_enqueue_scripts', array( $this,'my_admin_head'));
    }

    function showData(){
        return '<h1>My shortcode content</h1>' ;
    }
}

$object=new stockData();

Se você deseja acessar o conteúdo de shortcode de outra classe. Você pode fazer assim.

class my_PluginClass {

  public function __construct( $Object ) {

    $test = add_shortcode( 'your_shortcode_name', array( $Object, 'your_method_name' ) );

  }

}

class CustomHandlerClass{

  public function your_method_name( $atts, $content ) {
     return '<h1>My shortcode content</h1>' ;
  }
}

$Customobject  = new CustomHandlerClass();
$Plugin         = new my_PluginClass( $Customobject );
Pavnish Yadav
fonte
1
Eu realmente gosto desta solução. É realmente limpo e compreensível. O meu desenvolvedor React.js está feliz com isso.
AaronDancer 13/04
1

Certifique-se de criar uma instância da sua classe antes de usá-la, a menos que você tenha certeza de que ela deve ser chamada estaticamente. Quando você chama um método estaticamente, não usa nenhuma instância e, portanto, ele não tem acesso a nenhuma variável ou método membro.

woony
fonte