Errore PHP con gestore shortcode di una classe


13

Attualmente sto usando il seguente flusso generico per aggiungere lo shortcode per un plugin.

class MyPlugin {

    private $myvar;

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

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

Ora quando questa classe e il suo metodo vengono chiamati ottengo il seguente errore.

Errore irreversibile: utilizzo di $ this quando non nel contesto dell'oggetto in ...

(La riga n. È dove ho stampato il $this->myvar)

È un problema alla fine di Wordpress o c'è qualcosa che sto facendo di sbagliato? Sembra essere qualcosa di veramente semplice.


fuori tema - crea la funzione static.
Kaiser

Risposte:


31

Come dice l'errore, è necessario utilizzare un'istanza della classe $this. Esistono almeno tre possibilità:

Rendi tutto statico

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

Ma non è più il vero OOP, solo lo spazio dei nomi.

Crea prima un oggetto reale

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

Questo ... funziona. Ma ti imbatti in alcuni problemi oscuri se qualcuno vuole sostituire lo shortcode.

Quindi aggiungi un metodo per fornire l'istanza della 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' ] );

Ora, quando qualcuno vuole ottenere l'istanza dell'oggetto, deve solo scrivere:

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

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

Vecchia soluzione: crea l'oggetto nella tua 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' ) );

grazie amico ... queste sono informazioni inestimabili poiché wordpress.org non ha detto molto sulla loro pagina di documentazione add_shortcode. Avevo capito la soluzione, ma dal momento che l'hai esclusa come una cattiva pratica e hai una soluzione migliore, quindi contrassegno questo problema come risolto :)
xmaestro

Mi dispiace davvero a scavare questa vecchia questione, ma potrebbe prego di elaborare ciò che questa linea fa: NULL === self::$instance and self::$instance = new self;? Sono un po 'confuso perché ===e andsono usati, ma senza if, se sai cosa intendo.
Sven,

@Sven Questo è un controllo per impedire una seconda istanza. Rende questa classe un Singleton ... Non lo farei al giorno d'oggi. Riscriverò questa risposta.
fuxia

Grazie per quello! Penso che ora sono sulla strada giusta, anche se è sorprendente quanto possa essere complicato utilizzare WordPress e OOP ;-)
Sven

2
Il core di @Sven WordPress è scritto praticamente il più anti-OOP possibile. Anche il nuovo codice ignora tutto ciò che il resto del mondo PHP ha imparato negli ultimi dieci anni, ad esempio l'iniezione di dipendenza. Quindi sì, OOP nei plugin e nei temi di WordPress è sempre hacker. : /
fuxia

7

È possibile utilizzare in questo modo, shortcode all'interno della 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 si desidera accedere al contenuto dello shortcode da un'altra classe. Puoi fare così.

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
Mi piace molto questa soluzione. È davvero pulito e comprensibile. Il lato sviluppatore di React.js è contento di questo.
AaronDancer

1

Assicurati di creare un'istanza della tua classe prima di usarla a meno che tu non sia sicuro che debba essere chiamato staticamente. Quando chiami staticamente un metodo, non usi alcuna istanza e quindi non ha accesso a nessuna variabile o metodo membro.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.