Errore PHP con gestore shortcode da una classe

10 ago 2012, 10:28:39
Visualizzazioni: 19.9K
Voti: 16

Attualmente sto utilizzando 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') );

Quando questa classe e il suo metodo vengono chiamati, ricevo il seguente errore.

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

(Il numero di riga è dove ho stampato $this->myvar)

È un problema di WordPress o sto facendo qualcosa di sbagliato? Sembra essere qualcosa di davvero semplice.

1
Commenti

fuori tema - rendi la funzione static.

kaiser kaiser
27 set 2012 18:21:02
Tutte le risposte alla domanda 3
11
37

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

Rendere tutto statico

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

    static function foo()
    {
        return self::$var; // non usare mai echo o print in uno shortcode!
    }
}
add_shortcode( 'baztag', array( 'My_Plugin', 'foo' ) );

Ma questa non è più vera OOP, solo un namespacing.

Creare prima un oggetto reale

class My_Plugin
{
    private $var = 'foo';

    public function foo()
    {
        return $this->var; // non usare mai echo o print in uno shortcode!
    }
}

$My_Plugin = new My_Plugin;

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

Questo... funziona. Ma si possono incontrare 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; // restituisce l'oggetto
    }

    public function foo()
    {
        return $this->var; // non usare mai echo o print in uno shortcode!
    }
}

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

Ora, quando qualcuno vuole ottenere l'istanza dell'oggetto, basta che scriva:

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

if ( is_a( $shortcode_handler, 'My_Plugin ' ) )
{
    // fai qualcosa con quell'istanza.
}

Vecchia soluzione: creare l'oggetto nella tua classe

class My_Plugin
{
    private $var = 'foo';

    protected static $instance = NULL;

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

        return self::$instance; // restituisce l'oggetto
    }

    public function foo()
    {
        return $this->var; // non usare mai echo o print in uno shortcode!
    }
}

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

grazie mille... queste informazioni sono preziosissime visto che wordpress.org non riporta tutto questo nella loro pagina di documentazione su add_shortcode. Avevo già trovato una soluzione ma dato che l'hai indicata come una cattiva pratica e hai una soluzione migliore, segno questo problema come risolto :)

xmaestro xmaestro
10 ago 2012 10:49:59

Mi dispiace davvero riesumare questa vecchia domanda, ma potresti spiegare cosa fa questa riga: NULL === self::$instance and self::$instance = new self;? Sono un po' confuso perché vengono usati === e and, ma senza un if, se capisci cosa intendo.

Sven Sven
3 gen 2015 14:17:03

@Sven Questo è un controllo per prevenire una seconda istanza. Rende questa classe un Singleton... Oggi non lo farei più. Riscriverò questa risposta.

fuxia fuxia
3 gen 2015 14:18:47

Grazie per questo! Penso di essere sulla strada giusta ora, anche se è sorprendente quanto possa essere complicato usare WordPress & OOP ;-)

Sven Sven
3 gen 2015 14:38:57

@Sven Il core di WordPress è scritto in modo il più possibile anti-OOP. Anche il nuovo codice ignora tutto ciò che il resto del mondo PHP ha imparato negli ultimi dieci anni, come l'injection delle dipendenze per esempio. Quindi sì, l'OOP nei plugin e nei temi di WordPress è sempre un po' un ripiego. :/

fuxia fuxia
3 gen 2015 14:42:33

Il dispositivo add_shortcode viene dal lato oscuro! Questo codice è davvero incredibile. +1 sul fatto che WordPress debba convertire o deportare il $#ANTIOOP;. La deprecazione ha bisogno di piani di migrazione in modo importante.

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

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

Come posso passare dei parametri a 'get_instance'? Come 'get_instance[params]'? Grazie.

b_dubb b_dubb
10 dic 2018 20:33:57

@b_dubb Passi i parametri al costruttore.

fuxia fuxia
10 dic 2018 20:35:33

@fuxia e come sarebbe esattamente... ?

b_dubb b_dubb
12 dic 2018 18:18:25

@b_dubb Oh, aspetta, ora ho capito la tua domanda. Non passi affatto parametri a quella funzione.

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
Mostra i restanti 6 commenti
1
10

Puoi usarlo così, 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>Il contenuto del mio shortcode</h1>' ;
    }
}

$object=new stockData();

Se vuoi accedere al contenuto dello shortcode da un'altra classe. Puoi farlo 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>Il contenuto del mio shortcode</h1>' ;
  }
}

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

Mi piace molto questa soluzione. È davvero pulita e comprensibile. La parte di me che è sviluppatore React.js è felice di ciò.

AaronDancer AaronDancer
13 apr 2017 22:44:03
0

Assicurati di creare un'istanza della tua classe prima di utilizzarla, a meno che tu non sia certo che debba essere chiamata staticamente. Quando chiami un metodo staticamente, non utilizzi alcuna istanza e quindi non hai accesso a variabili o metodi membro.

10 ago 2012 10:46:20