PHP-Fehler mit Shortcode-Handler aus einer Klasse


13

Momentan verwende ich den folgenden allgemeinen Ablauf zum Hinzufügen des Shortcodes für ein Plugin.

class MyPlugin {

    private $myvar;

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

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

Wenn diese Klasse und ihre Methode aufgerufen werden, erhalte ich den folgenden Fehler.

Schwerwiegender Fehler: Verwenden von $ this, wenn es sich nicht im Objektkontext befindet in ...

(Zeile Nr. Ist, wo ich das gedruckt habe $this->myvar)

Ist das ein Problem bei Wordpress oder gibt es etwas, was ich falsch mache? Es scheint etwas wirklich Einfaches zu sein.


off topic - mach die funktion static.
Kaiser

Antworten:


31

Wie der Fehler besagt, müssen Sie eine Instanz der Klasse verwenden $this. Es gibt mindestens drei Möglichkeiten:

Mach alles statisch

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

Aber das ist kein echtes OOP mehr, nur noch Namensraum.

Erstellen Sie zuerst ein reales Objekt

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

Das funktioniert. Sie haben jedoch einige undurchsichtige Probleme, wenn jemand den Shortcode ersetzen möchte.

So fügen Sie eine Methode hinzu, um die Klasseninstanz bereitzustellen:

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

Wenn jemand die Objektinstanz erhalten möchte, muss er nur schreiben:

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

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

Alte Lösung: Erstellen Sie das Objekt in Ihrer Klasse

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

Danke, Mann ... das ist eine unschätzbare Information, da wordpress.org nicht so viel auf der Dokumentationsseite add_shortcode erzählt hat. Ich hatte die Lösung herausgefunden, aber da Sie das als eine schlechte Praxis ausgeschlossen haben und Sie eine bessere Lösung haben, markiere ich dieses Problem als gelöst :)
xmaestro

Ich bin wirklich leid , diese alte Frage zu graben, aber könnten Sie bitte erarbeiten , was diese Zeile tut: NULL === self::$instance and self::$instance = new self;? Ich bin da ein bisschen verwirrt ===und werde andbenutzt, aber ohne if, wenn du weißt was ich meine.
Sven

@Sven Dies ist eine Überprüfung, um eine zweite Instanz zu verhindern. Das macht diese Klasse zu einem Singleton… das würde ich heutzutage nicht tun. Ich werde diese Antwort umschreiben.
fuxia

Dank dafür! Ich denke, jetzt bin ich auf dem richtigen Weg, obwohl es erstaunlich ist, wie kompliziert es sein kann, WordPress & OOP zu verwenden ;-)
Sven

2
@Sven WordPress Core ist so gut wie möglich gegen OOP geschrieben. Selbst neuer Code ignoriert all die Dinge, die der Rest der PHP-Welt in den letzten zehn Jahren gelernt hat, zum Beispiel die Abhängigkeitsinjektion. Also ja, OOP in WordPress Plugins und Themes ist immer hackisch. : /
fuxia

7

Sie können so einen Shortcode innerhalb der Klasse verwenden

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

Wenn Sie auf Shortcode-Inhalte einer anderen Klasse zugreifen möchten. Das kannst du machen.

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

1
Ich mag diese Lösung wirklich. Es ist wirklich sauber und verständlich. Die Entwicklerseite von React.j ist damit zufrieden.
AaronDancer

1

Stellen Sie sicher, dass Sie eine Instanz Ihrer Klasse erstellen, bevor Sie sie verwenden, es sei denn, Sie sind sicher, dass sie statisch aufgerufen werden soll. Wenn Sie eine Methode statisch aufrufen, verwenden Sie keine Instanzen und haben daher keinen Zugriff auf Membervariablen oder -methoden.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.