add_action with a class method is causing fatal errors

I wasn’t sure if this was a PHP issue (suited for StackOverflow) or a WordPress issue (suited for StackExchange), however since my issue appears to be with the add_action() function, I have placed the question here.

Here’s some simplified code which causes the same issue (to avoid re-posting my couple-hundred line plugin):

Read More
<?php
$class = new MyClass();
add_action('init', array($class, 'init'));

class MyClass {
    public static function init() {
        $this->core();
    }
    public static function core() {
        echo "I never get this far...";
    }
}
?>

I get the following error:

Fatal error: Using $this when not in object context in /home/coupon/public_html/wp-content/plugins/test.php on line 7

If my add_action() call were instead:

add_action('init', 'MyClass::init');

Then I would understand this error (since the function was called statically and there is no instance of DEMenu for $this to point to), however I don’t understand why this is happening since I used an array and passed an instance of the class.

My specific issue is actually related to this problem. I created a custom Walker class then used the wp_nav_menu_args filter to pass my custom Walker. I get this error in class-wp-walker.php on line 185. The line in particular is:

$id_field = $this->db_fields['id'];

Any ideas?

EDIT –

test.php is now functioning properly, but the original issue is not solved… As such here’s my plugin’s index.php file (simplified):

$DEMenu = new DEMenu();

class DEMenu {

    function DEMenu() {
        if (is_admin()) {
            add_action('admin_menu', array(&$this, 'admin'));
        } else {
            add_action('init', array(&$this, 'core'));
        }
    }

    public function admin() {
        /* Not important */
    }

    public function core() {
        add_filter('wp_nav_menu_args', array(&$this, 'add_walker'));
    }

    public function add_walker( $args ) {
        $args['walker'] = 'DEMenu_Walker';
        return $args;
    }

}

class DEMenu_Walker extends Walker_Nav_Menu {

    function __construct() {
        die("We made it to the constructor!");
    }

}

As mentioned above, I am getting the following error:

Fatal error: Using $this when not in object context in /home/coupon/public_html/wp-includes/class-wp-walker.php on line 185

Since the above test.php was failing and since the Walker_Nav_Menu class never has this error normally (not until I added my plugin) I figured the issue was with the one of my add_action() or add_filter() calls. However since it is still failing I’m not entirely sure where the issue is…

FINAL EDIT –

Carefully re-reading the walk_nav_menu_tree() function, I have found the issue with my walker class…

function walk_nav_menu_tree( $items, $depth, $r ) {
        $walker = ( empty($r->walker) ) ? new Walker_Nav_Menu : $r->walker;
        $args = array( $items, $depth, $r );

        return call_user_func_array( array(&$walker, 'walk'), $args );
}

Since $walker is being set to $r->walker it is a string, not an instance of a class. Therefore the class method is called statically instead of via an instance of the class. Instead of:

$args['walker'] = 'DEMenu_Walker';

I should have:

$args['walker'] = new DEMenu_Walker();

Task: Call a class method as a hook for a WordPress plugin so that the $this variable is not broken

Related posts

Leave a Reply

3 comments

  1. Try:

    <?php
    $class = new MyClass();
    
    class MyClass {
        public function MyClass() {
           add_action('init', array($this, 'core'));
        }
        public static function core() {
            echo "I never get to here";
        }
    }
    ?>
    
  2. $class = new MyClass();
    add_action('init', array($class, 'init'));
    

    That is correct! You have the PHP-Error, you must Add a Constructor to your Class with returnin the “Instance/Object” like:

    class MyClass {
        function __construct() {
            return $this;
        }
    
        /* The other Methods... */
    }
    
  3. If you are to deal with static class and methods

    class Kc_Class{
    
      static function init(){
    
          add_action('some_hook',array(__CLASS__,'my_static_method'));
    
      }    
      static function my_static_method(){
    
        ...
      }
    }
    

    Then make a call to your init method

    Kc_Class::init();