Errore PHP con gestore shortcode da una classe
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.

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

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

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 Questo è un controllo per prevenire una seconda istanza. Rende questa classe un Singleton... Oggi non lo farei più. Riscriverò questa risposta.

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

@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. :/

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.

add_filter( 'get_my_plugin_instance', [ $this, 'get_instance' ] );
Come posso passare dei parametri a 'get_instance'? Come 'get_instance[params]'? Grazie.

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

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