Błąd PHP z obsługą shortcode z klasy

13

Obecnie używam następującego ogólnego przepływu do dodawania krótkiego kodu dla wtyczki.

class MyPlugin {

    private $myvar;

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

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

Teraz, gdy ta klasa i jej metoda są nazywane, pojawia się następujący błąd.

Błąd krytyczny: użycie $ this, gdy nie jest w kontekście obiektowym w ...

(Numer linii to miejsce, w którym wydrukowałem $this->myvar)

Czy to problem po stronie Wordpress, czy coś robię źle? To wydaje się być bardzo proste.

Xmaestro
źródło
nie na temat - włącz funkcję static.
kaiser

Odpowiedzi:

31

Jak mówi błąd, potrzebujesz instancji klasy do użycia $this. Istnieją co najmniej trzy możliwości:

Uczyń wszystko statycznym

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

Ale to już nie jest prawdziwy OOP, tylko przestrzeń nazw.

Najpierw stwórz prawdziwy obiekt

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

To działa. Ale jeśli ktoś chce zastąpić krótki kod , napotkasz jakieś niejasne problemy .

Dodaj więc metodę, aby zapewnić instancję klasy:

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

Teraz, gdy ktoś chce uzyskać instancję obiektu, musi po prostu napisać:

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

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

Stare rozwiązanie: utwórz obiekt w swojej klasie

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' ) );
fuxia
źródło
thanx man ... to bezcenne informacje, ponieważ wordpress.org nie powiedział zbyt wiele na stronie dokumentacji add_shortcode. Ja zorientowali się rozwiązanie, ale ponieważ trzeba wykluczyć, że za złą praktyką i masz lepsze rozwiązania, więc oznaczyć ten problem jako rozwiązany :)
xmaestro
Jestem naprawdę przykro wykopać ten stary pytanie, ale może pluskać opracować co robi ten wiersz: NULL === self::$instance and self::$instance = new self;? Jestem trochę zdezorientowany, ponieważ ===i andsą używane, ale bez if, jeśli wiesz, co mam na myśli.
Sven
@ Sven To jest czek, aby zapobiec drugiej instancji. To sprawia, że ​​ta klasa jest Singletonem… W dzisiejszych czasach nie zrobiłbym tego. Przepiszę tę odpowiedź.
fuxia
Dziękuję za to! Myślę, że teraz jestem na dobrej drodze, choć zadziwiające, jak skomplikowane może być korzystanie z WordPress & OOP ;-)
Sven
2
@Sven Rdzeń WordPress jest napisany w jak największym stopniu anty-OOP. Nawet nowy kod ignoruje wszystkie rzeczy, których reszta świata PHP nauczyła się w ciągu ostatnich dziesięciu lat, na przykład zastrzyk zależności. Więc tak, OOP we wtyczkach i motywach WordPress jest zawsze hackerskie. : /
fuxia
7

Możesz użyć w ten sposób krótkiego kodu wewnątrz klasy

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

Jeśli chcesz uzyskać dostęp do zawartości shortcode z innej klasy. Możesz to zrobić w ten sposób.

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 );
Pavnish Yadav
źródło
1
Naprawdę podoba mi się to rozwiązanie. Jest naprawdę czysty i zrozumiały. Strona dewelopera React.js jest z tego zadowolona.
AaronDancer
1

Upewnij się, że wykonałeś instancję swojej klasy przed jej użyciem, chyba że masz pewność, że ma ona zostać wywołana statycznie. Kiedy wywołujesz metodę statycznie, nie używasz żadnych instancji, a zatem nie ma ona dostępu do żadnych zmiennych składowych ani metod.

woony
źródło