Error de PHP con el manejador de shortcode desde una clase

10 ago 2012, 10:28:39
Vistas: 19.9K
Votos: 16

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

class MyPlugin {

    private $myvar;

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

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

Ahora cuando esta clase y su método son llamados obtengo el siguiente error.

Fatal error: Using $this when not in object context in ...

(El número de línea es donde he impreso $this->myvar)

¿Es esto un problema de WordPress o hay algo que estoy haciendo mal? Parece ser algo realmente simple.

1
Comentarios

fuera de tema - haz la función static.

kaiser kaiser
27 sept 2012 18:21:02
Todas las respuestas a la pregunta 3
11
37

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

Hacer todo estático

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

    static function foo()
    {
        return self::$var; // ¡nunca uses echo o print en un shortcode!
    }
}
add_shortcode( 'baztag', array( 'My_Plugin', 'foo' ) );

Pero esto ya no es realmente POO, solo es un espacio de nombres.

Crear un objeto real primero

class My_Plugin
{
    private $var = 'foo';

    public function foo()
    {
        return $this->var; // ¡nunca uses echo o print en un shortcode!
    }
}

$My_Plugin = new My_Plugin;

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

Esto... funciona. Pero puedes encontrarte con problemas oscuros si alguien quiere reemplazar el shortcode.

Así que añade un método para proporcionar la instancia de la 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; // devuelve el objeto
    }

    public function foo()
    {
        return $this->var; // ¡nunca uses echo o print en un shortcode!
    }
}

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

Ahora, cuando alguien quiera 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 ' ) )
{
    // hacer algo con esa instancia.
}

Solución antigua: crear el objeto en tu clase

class My_Plugin
{
    private $var = 'foo';

    protected static $instance = NULL;

    public static function get_instance()
    {
        // crear un objeto
        NULL === self::$instance and self::$instance = new self;

        return self::$instance; // devuelve el objeto
    }

    public function foo()
    {
        return $this->var; // ¡nunca uses echo o print en un shortcode!
    }
}

add_shortcode( 'baztag', array( My_Plugin::get_instance(), 'foo' ) );
10 ago 2012 10:45:10
Comentarios

gracias hombre... esa información no tiene precio ya que wordpress.org no menciona tanto en su página de documentación de add_shortcode. Había encontrado la solución pero como has descartado eso como una mala práctica y tienes una mejor solución, marco este problema como resuelto :)

xmaestro xmaestro
10 ago 2012 10:49:59

Lamento mucho desenterrar esta antigua pregunta, pero ¿podrías explicar qué hace esta línea: NULL === self::$instance and self::$instance = new self;? Estoy un poco confundido porque se usan === y and, pero sin un if, si sabes a lo que me refiero.

Sven Sven
3 ene 2015 14:17:03

@Sven Esto es una verificación para evitar una segunda instancia. Hace que esta clase sea un Singleton... No lo haría hoy en día. Voy a reescribir esta respuesta.

fuxia fuxia
3 ene 2015 14:18:47

¡Gracias por eso! Creo que ahora voy por el camino correcto, aunque es asombroso lo complicado que puede ser usar WordPress y POO ;-)

Sven Sven
3 ene 2015 14:38:57

@Sven El núcleo de WordPress está escrito de la manera más anti-POO posible. Incluso el código nuevo ignora todo lo que el resto del mundo PHP ha aprendido en los últimos diez años, como la inyección de dependencias. Así que sí, la POO en plugins y temas de WordPress siempre es un poco chapucera. :/

fuxia fuxia
3 ene 2015 14:42:33

¡El dispositivo add_shortcode es del lado oscuro! Este código es bastante genial. +1 en el hecho de que WordPress necesita portar o deportar el $#ANTIOOP;. La depreciación necesita planes de migración de manera importante.

Nathan Powell Nathan Powell
17 feb 2016 07:57:59

add_filter( 'get_my_plugin_instance', [ $this, 'get_instance' ] );

¿Cómo puedo pasar parámetros en 'get_instance'? ¿Como 'get_instance[params]'? Gracias.

b_dubb b_dubb
10 dic 2018 20:33:57

@b_dubb Pasas los parámetros al constructor.

fuxia fuxia
10 dic 2018 20:35:33

@fuxia ¿y eso se vería como...?

b_dubb b_dubb
12 dic 2018 18:18:25

@b_dubb Ah, espera, ahora entiendo tu pregunta. No pasas parámetros a eso en absoluto.

fuxia fuxia
12 dic 2018 18:35:10

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

b_dubb b_dubb
28 dic 2018 06:46:42
Mostrar los 6 comentarios restantes
1
10

Puedes usarlo 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>Mi contenido del shortcode</h1>' ;
    }
}

$object=new stockData();

Si deseas acceder al contenido del shortcode desde otra clase. Puedes hacerlo 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>Mi contenido del shortcode</h1>' ;
  }
}

$Customobject  = new CustomHandlerClass();
$Plugin         = new my_PluginClass( $Customobject );
25 jun 2015 10:57:51
Comentarios

Realmente me gusta esta solución. Es muy limpia y comprensible. La parte de mí que es desarrollador React.js está contenta con esto.

AaronDancer AaronDancer
13 abr 2017 22:44:03
0

Asegúrate de crear una instancia de tu clase antes de usarla, a menos que estés seguro de que debe llamarse estáticamente. Cuando llamas a un método de forma estática, no utilizas ninguna instancia y, por lo tanto, no tiene acceso a ninguna variable o método miembro.

10 ago 2012 10:46:20