Why does using $this inside a class in a Wordpress plugin throw a fatal error?

11,355

Solution 1

So, I've seem to have fixed it, by going back to the basics and asking Google the humble question: "Using classes in Wordpress plugins".

Both the article by Jay Fortner and one on dConstructing.com were helpful.

Basically, I'm now calling add_menu_page and add_submenu_page from within the class. I was under the impression those functions somehow created an object, but they obviously don't.

My code now looks something like this and I'm able to call the declared class variable without error:

if (!class_exists("MyClass")) {
  class MyClass {
    var $test = 'Test variable';

    function __construct() {
      add_action('admin_menu', 'my_plugin_menu');
    }

    function my_plugin_menu() {
      add_menu_page('My Plugin', 'My Plugin', 'manage_options', 'my-plugin', array(&$this, 'index'));
      add_submenu_page('my-plugin', 'Add New Thing', 'Add New', 'manage_options', 'my-plugin-add', array(&$this, 'add'));
    }

    public function index() {
      //Index code
    }

    public function add() {
      echo $this->test;
    }
  }
  new MyClass;
}

Solution 2

This is no longer true.

Don't forget, if you pass in the class, you may want to pass it by reference, you can even pass a classes own functions using &$this inside of a class and continue to modify the same instance, this helps to not have to recreate a class everytime you call a different part of the plugin but the same class.

From: https://codex.wordpress.org/Function_Reference/do_action_ref_array

As of PHP 5.4, the array is no longer passed by reference despite the function's name. You cannot even use the reference sign '&' because call time pass by reference now throws an error. What you can do is pass the reference pointer as an array element. Doing so does require all callbacks added to the action to expect a reference pointer. This is not something you will see in WordPress actions. This technique is provided for informational purposes only.

$Class = new MyClass();
 add_menu_page(
       'My Plugin',
        'My Plugin',
        'manage_options',
        'my-plugin',
        array(&$Class, 'index')

Or

$myClass= new MyClass ;

add_action('admin_menu', array( $myClass, 'admin_menu' ) );

class MyClass 
{
    public function admin_menu()
    {   
        add_menu_page('MyMenu', 'MyMenu', 'read', 'mymenu', array( $this, 'action' ));  
    }
    public function action()
    {   
        //Do something here
    }
}

Solution 3

What you should do is the following:

function my_plugin_menu()
{
add_menu_page('My Plugin', 'My Plugin', 'manage_options', 'my-plugin', array(new MyClass, 'index'));
add_submenu_page('my-plugin', 'Add New Thing', 'Add New', 'manage_options', 'my-plugin-add', array('MyClass', 'add'));
}

Using array('MyClass', 'index') cause php to execute the method as a static methed, but passing an actual object as the first argument will call the method via the object.

function my_plugin_menu()
{
    $Class = new MyClass();
    add_menu_page(
        'My Plugin',
        'My Plugin',
        'manage_options',
        'my-plugin',
        array($Class, 'index')
    );
}

Would also work if you want to reuse the object.

Solution 4

depends how the class is being called, statically Class::method() will throw errors. If that is the case i think you need to use self::$test; but could be wrong.

Share:
11,355
mensch
Author by

mensch

I'm a graphic designer and web developer, currently developing a lot with Laravel.

Updated on July 29, 2022

Comments

  • mensch
    mensch almost 2 years

    I'm in the process of writing a Wordpress plugin which creates a page in the admin area, as well as executing some frontend code.

    The code below throws a nice Fatal error: Using $this when not in object context error. Which is rather mystifying, as the variable is called inside the class.

    Maybe I'm not following the intended Wordpress plugin structure for functions and classes, but the conceptual code below was created using the relevant entries on plugin development in the Wordpress Codex.

    Could somebody explain why the error is triggered, because when I create an instance of the class outside of the Wordpress codebase everything is fine.

    if (!class_exists("MyClass")) {
      class MyClass {
        var $test = 'Test variable';
    
        public function index() {
          //Index code
        }
    
        public function add() {
          echo $this->test;
        }
      }
    }
    
    add_action('admin_menu', 'my_plugin_menu');
    
    function my_plugin_menu() {
      add_menu_page('My Plugin', 'My Plugin', 'manage_options', 'my-plugin', array('MyClass', 'index'));
      add_submenu_page('my-plugin', 'Add New Thing', 'Add New', 'manage_options', 'my-plugin-add', array('MyClass', 'add'));
    }
    
  • mensch
    mensch about 13 years
    I'm not sure how Wordpress calls the class, but using self::test instead of $this->test doesn't resolve the error, I'm afraid.
  • Ari
    Ari almost 10 years
    Hey..., the code is not working for me. So, I change this add_action('admin_menu', 'my_plugin_menu'); function to this add_action('admin_menu', array($this, 'my_plugin_menu'));
  • Vishal Tanna
    Vishal Tanna over 7 years
    Inside action i added form tag. So what should i pass in action and where can i get post value? Thanks in advance.
  • geilt
    geilt over 7 years
    Check the $_POST array for post values.