Eroare PHP cu handler-ul shortcode dintr-o clasă

10 aug. 2012, 10:28:39
Vizualizări: 19.9K
Voturi: 16

Î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.

1
Comentarii

off topic - faceți funcția static.

kaiser kaiser
27 sept. 2012 18:21:02
Toate răspunsurile la întrebare 3
11
37

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' ) );
10 aug. 2012 10:45:10
Comentarii

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

xmaestro xmaestro
10 aug. 2012 10:49:59

Î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 Sven
3 ian. 2015 14:17:03

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

fuxia fuxia
3 ian. 2015 14:18:47

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 Sven
3 ian. 2015 14:38:57

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

fuxia fuxia
3 ian. 2015 14:42:33

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.

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

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 b_dubb
10 dec. 2018 20:33:57

@b_dubb Pasezi parametrii către constructor.

fuxia fuxia
10 dec. 2018 20:35:33

@fuxia și asta ar arăta cam așa... ?

b_dubb b_dubb
12 dec. 2018 18:18:25

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

fuxia fuxia
12 dec. 2018 18:35:10

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

b_dubb b_dubb
28 dec. 2018 06:46:42
Arată celelalte 6 comentarii
1
10

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 );
25 iun. 2015 10:57:51
Comentarii

Îmi place foarte mult această soluție. Este foarte curată și ușor de înțeles. Parte din mine care este dezvoltator React.js este mulțumită de asta.

AaronDancer AaronDancer
13 apr. 2017 22:44:03
0

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.

10 aug. 2012 10:46:20