13

Currently i am using the following generic flow for adding the shortcode for a plugin.

class MyPlugin {

    private $myvar;

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

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

Now when this class and it's method are called i get the following error.

Fatal error: Using $this when not in object context in ...

(Line no is where i have printed the $this->myvar)

Is this a problem on Wordpress's end or is there is something i'm doing wrong? It seems to be something really simple.

  • off topic - make the function static. – kaiser Sep 27 '12 at 15:21
30

As the error says you need an instance of the class to use $this. There are at least three possibilities:

Make everything static

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

But that’s not real OOP anymore, just namespacing.

Create a real object first

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

This … works. But you run into some obscure problems if anyone wants to replace the shortcode.

So add a method to provide the class instance:

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

Now, when someone wants to get the object instance, s/he just has to write:

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

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

Old solution: create the object in your class

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' ) );
  • thanx man ... thats priceless info since wordpress.org did not tell this much on their add_shortcode documentation page. I had figured out the solution but since you have ruled that out as a bad practice and you have a better solution so i mark this problem as solved:) – xmaestro Aug 10 '12 at 7:49
  • I am really sorry to dig up this old question, but could you plase elaborate what this line does: NULL === self::$instance and self::$instance = new self;? I am a bit confused because === and and are used, but without if, if you know what I mean. – Sven Jan 3 '15 at 12:17
  • @Sven This is a check to prevent a second instance. It makes this class a Singleton … I wouldn’t do that nowadays. I will rewrite this answer. – fuxia Jan 3 '15 at 12:18
  • Thanks for that! I think now I am on the right track, although it is astonishing how complicated it can be using WordPress & OOP ;-) – Sven Jan 3 '15 at 12:38
  • 2
    @Sven WordPress core is written pretty much as anti-OOP as possible. Even new code ignores all the things the rest of the PHP world has learned during the last ten years, dependency injection for example. So yes, OOP in WordPress plugins and themes is always hackish. :/ – fuxia Jan 3 '15 at 12:42
7

You can use like this, shortcode inside the Class

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

If you want access shortcode content from another class. You can do like this.

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
    I really like this solution. It's really clean and understandable. The React.js developer side of me is happy with this. – AaronDancer Apr 13 '17 at 19:44
1

Make sure that you make an instance of your class before using it unless you are sure it's supposed to be called statically. When you call a method statically, you don't use any instances and therefore it doesn't have access to any member variables or methods.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.