Error de PHP con el controlador de shortcode de una clase

13

Actualmente estoy usando el siguiente flujo genérico para agregar el shortcode para un complemento.

class MyPlugin {

    private $myvar;

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

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

Ahora, cuando se llama a esta clase y su método, obtengo el siguiente error.

Error fatal: usar $ this cuando no está en el contexto del objeto en ...

(La línea no es donde he impreso $this->myvar)

¿Es este un problema al final de Wordpress o hay algo que estoy haciendo mal? Parece ser algo realmente simple.

xmaestro
fuente
fuera del tema : haga la función static.
kaiser

Respuestas:

31

Como dice el error, necesita una instancia de la clase para usar $this. Hay al menos tres posibilidades:

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

Pero eso ya no es OOP real, solo espacios de nombres.

Crea un objeto real primero

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

Esto funciona. Pero te encuentras con algunos problemas oscuros si alguien quiere reemplazar el shortcode.

Entonces agregue un método para proporcionar la instancia de clase:

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

Ahora, cuando alguien quiere obtener la instancia del objeto, solo tiene que escribir:

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

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

Solución anterior: crea el objeto en tu clase

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
fuente
gracias hombre ... esa es información invaluable ya que wordpress.org no dijo mucho en su página de documentación add_shortcode. Había descubierto la solución, pero como lo descartó como una mala práctica y tiene una mejor solución, entonces marco este problema como resuelto :)
xmaestro
Realmente lamento desenterrar esta vieja pregunta, pero ¿podrías explicar qué hace esta línea NULL === self::$instance and self::$instance = new self;? Estoy un poco confundido porque ===y andse usan, pero sin if, si sabes a lo que me refiero.
Sven
@Sven Esta es una comprobación para evitar una segunda instancia. Hace de esta clase un Singleton ... No haría eso hoy en día. Reescribiré esta respuesta.
fuxia
¡Gracias por eso! Creo que ahora estoy en el camino correcto, aunque es sorprendente lo complicado que puede ser usar WordPress & OOP ;-)
Sven
2
El núcleo de @Sven WordPress está escrito lo más anti-OOP posible. Incluso el nuevo código ignora todas las cosas que el resto del mundo PHP ha aprendido durante los últimos diez años, por ejemplo, la inyección de dependencia. Entonces sí, OOP en plugins y temas de WordPress siempre es hack. : /
fuxia
7

Puedes usar así, shortcode dentro de la clase

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

Si desea acceder al contenido de shortcode de otra clase. Puedes hacer así.

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
fuente
1
Realmente me gusta esta solución. Es realmente limpio y comprensible. El lado desarrollador de React.js de mí está contento con esto.
AaronDancer
1

Asegúrese de hacer una instancia de su clase antes de usarla, a menos que esté seguro de que se debe llamar estáticamente. Cuando llama a un método de forma estática, no utiliza ninguna instancia y, por lo tanto, no tiene acceso a ninguna variable o método miembro.

woony
fuente