Eroare PHP cu handler-ul shortcode dintr-o clasă
În prezent folosesc următorul flux generic pentru adăugarea shortcode-ului într-un plugin.
class MyPlugin {
private $myvar;
function baztag_func() {
print $this->myvar;
}
}
add_shortcode( 'baztag', array('MyPlugin', 'baztag_func') );
Acum când această clasă și metoda sa sunt apelate, primesc următoarea eroare.
Fatal error: Using $this when not in object context in ...
(Numărul liniei este acolo unde am afișat $this->myvar
)
Este aceasta o problemă din partea WordPress sau fac eu ceva greșit? Pare să fie ceva foarte simplu.

După cum indică eroarea, ai nevoie de o instanță a clasei pentru a folosi $this
. Există cel puțin trei posibilități:
Fă totul static
class My_Plugin
{
private static $var = 'foo';
static function foo()
{
return self::$var; // nu folosi echo sau print într-un shortcode!
}
}
add_shortcode( 'baztag', array( 'My_Plugin', 'foo' ) );
Dar asta nu mai este programare orientată pe obiecte (OOP), ci doar un mod de a organiza codul.
Creează mai întâi un obiect real
class My_Plugin
{
private $var = 'foo';
public function foo()
{
return $this->var; // nu folosi echo sau print într-un shortcode!
}
}
$My_Plugin = new My_Plugin;
add_shortcode( 'baztag', array( $My_Plugin, 'foo' ) );
Această abordare... funcționează. Dar poți întâmpina probleme obscure dacă cineva dorește să înlocuiască shortcode-ul.
Deci, adaugă o metodă care să ofere instanța clasei:
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; // returnează obiectul
}
public function foo()
{
return $this->var; // nu folosi echo sau print într-un shortcode!
}
}
add_shortcode( 'baztag', [ new My_Plugin, 'foo' ] );
Acum, când cineva dorește să obțină instanța obiectului, trebuie doar să scrie:
$shortcode_handler = apply_filters( 'get_my_plugin_instance', NULL );
if ( is_a( $shortcode_handler, 'My_Plugin ' ) )
{
// poți face ceva cu acea instanță.
}
Soluție veche: creează obiectul în interiorul clasei
class My_Plugin
{
private $var = 'foo';
protected static $instance = NULL;
public static function get_instance()
{
// creează un obiect
NULL === self::$instance and self::$instance = new self;
return self::$instance; // returnează obiectul
}
public function foo()
{
return $this->var; // nu folosi echo sau print într-un shortcode!
}
}
add_shortcode( 'baztag', array( My_Plugin::get_instance(), 'foo' ) );

mersi omule... asta e informație de neprețuit având în vedere că wordpress.org nu a oferit atâtea detalii în pagina lor de documentare pentru add_shortcode. Am găsit deja soluția, dar din moment ce ai subliniat că e o practică proastă și ai o soluție mai bună, marchez problema ca rezolvată:)

Îmi pare foarte rău să dezgrop această întrebare veche, dar ai putea, te rog, să explici ce face această linie: NULL === self::$instance and self::$instance = new self;
? Sunt puțin confuz pentru că sunt folosite ===
și and
, dar fără if
, dacă înțelegi ce vreau să spun.

@Sven Aceasta este o verificare pentru a preveni o a doua instanță. Face din această clasă un Singleton... Nu aș mai face asta în zilele noastre. Voi rescrie acest răspuns.

Mulțumesc pentru asta! Cred că acum sunt pe drumul cel bun, deși este uimitor cât de complicat poate fi să folosești WordPress & OOP ;-)

@Sven Nucleul WordPress este scris într-un mod cât se poate de anti-OOP. Chiar și codul nou ignoră toate lucrurile pe care restul lumii PHP le-a învățat în ultimii zece ani, cum ar fi injectarea dependențelor, de exemplu. Deci da, OOP în plugin-uri și teme WordPress este întotdeauna cam hackish. :/

Dispozitivul add_shortcode
este parte din partea întunecată! Acest cod este destul de mișto. +1 pentru faptul că WordPress trebuie să migreze sau să deporteze $#ANTIOOP;. Deprecarea necesită planuri de migrare într-un mod major.

add_filter( 'get_my_plugin_instance', [ $this, 'get_instance' ] );
Cum aș putea pasa parametri la 'get_instance'? Ca 'get_instance[params]'? Mulțumesc.

@b_dubb Oh, stai, acum am înțeles întrebarea ta. Nu transmiți parametri deloc acolo.

Puteți folosi astfel, shortcode în interiorul Clasei
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>Conținutul meu de shortcode</h1>' ;
}
}
$object=new stockData();
Dacă doriți să accesați conținutul shortcode-ului dintr-o altă clasă. Puteți face astfel.
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>Conținutul meu de shortcode</h1>' ;
}
}
$Customobject = new CustomHandlerClass();
$Plugin = new my_PluginClass( $Customobject );

Asigurați-vă că creați o instanță a clasei înainte de a o utiliza, cu excepția cazului în care sunteți sigur că aceasta ar trebui apelată static. Când apelați o metodă static, nu utilizați nicio instanță și, prin urmare, nu aveți acces la nicio variabilă sau metodă membru.
