Erreur PHP avec le gestionnaire de shortcode d'une classe

13

Actuellement, j'utilise le flux générique suivant pour ajouter le shortcode pour un plugin.

class MyPlugin {

    private $myvar;

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

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

Maintenant, lorsque cette classe et sa méthode sont appelées, j'obtiens l'erreur suivante.

Erreur fatale: utilisation de $ this en dehors du contexte de l'objet dans ...

(La ligne n'est pas l'endroit où j'ai imprimé le $this->myvar)

Est-ce un problème du côté de Wordpress ou y a-t-il quelque chose que je fais mal? Cela semble être quelque chose de vraiment simple.

xmaestro
la source
hors sujet - rendre la fonction static.
kaiser

Réponses:

31

Comme le dit l'erreur, vous avez besoin d'une instance de la classe à utiliser $this. Il y a au moins trois possibilités:

Rendez tout statique

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

Mais ce n'est plus du vrai POO, juste de l'espace de noms.

Créez d'abord un objet réel

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

Cela marche. Mais vous rencontrez des problèmes obscurs si quelqu'un veut remplacer le shortcode.

Ajoutez donc une méthode pour fournir l'instance de 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; // return the object
    }

    public function foo()
    {
        return $this->var; // never echo or print in a shortcode!
    }
}

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

Maintenant, quand quelqu'un veut obtenir l'instance d'objet, il lui suffit d'écrire:

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

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

Ancienne solution: créer l'objet dans votre classe

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
la source
merci ... c'est une information inestimable puisque wordpress.org n'a pas dit grand-chose sur leur page de documentation add_shortcode. J'avais trouvé la solution mais puisque vous avez exclu cela comme une mauvaise pratique et que vous avez une meilleure solution, je marque donc ce problème comme résolu :)
xmaestro
Je suis vraiment désolé de déterrer cette vieille question, mais pourriez - vous préciser ce que PLASE cette ligne fait: NULL === self::$instance and self::$instance = new self;? Je suis un peu confus car ===et andhabitué, mais sans if, si vous voyez ce que je veux dire.
Sven
@Sven Il s'agit d'une vérification pour empêcher une deuxième instance. Cela fait de cette classe un Singleton… Je ne ferais pas ça de nos jours. Je vais réécrire cette réponse.
fuxia
Merci pour ça! Je pense que maintenant je suis sur la bonne voie, bien qu'il soit étonnant de voir à quel point cela peut être compliqué d'utiliser WordPress & OOP ;-)
Sven
2
@Sven WordPress core est écrit à peu près aussi anti-OOP que possible. Même le nouveau code ignore tout ce que le reste du monde PHP a appris au cours des dix dernières années, l'injection de dépendance par exemple. Alors oui, OOP dans les plugins et thèmes WordPress est toujours hackeux. : /
fuxia
7

Vous pouvez utiliser comme ceci, shortcode à l'intérieur de la 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>My shortcode content</h1>' ;
    }
}

$object=new stockData();

Si vous souhaitez accéder au contenu de shortcode d'une autre classe. Vous pouvez faire comme ça.

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
la source
1
J'aime vraiment cette solution. C'est vraiment propre et compréhensible. Le côté développeur de React.js en est satisfait.
AaronDancer
1

Assurez-vous de créer une instance de votre classe avant de l'utiliser, sauf si vous êtes sûr qu'elle est censée être appelée statiquement. Lorsque vous appelez une méthode de manière statique, vous n'utilisez aucune instance et, par conséquent, elle n'a accès à aucune variable ou méthode membre.

woony
la source