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.


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' ) );

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 );

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.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.