0

I need some help, I've been through so many of these "similar" issues on stackoverflow and all over the web but nothing seems to be helping.

I'm new to wordpress and started creating a plugin using classes. when I run the plugin it throws the error "Call to undefined function add_menu_page()". I've checked the support docs on wordpress.org but that doesn't help either (https://codex.wordpress.org/Adding_Administration_Menus#Inserting_the_Pages)

heres my code below please can you tell me what I'm doing wrong:

class SetupAdminMenu {

public static function add_menu($menu)
{
    add_action('admin_menu', self::load_menu($menu) );
    //I've used it according to the docs as well
    //add_action('admin_menu', array(self, self::load_menu($menu) );
}

public static function load_menu($menu)
{
    $page = add_menu_page( $menu['page_title'], $menu['menu_title'], $menu['capability'], $menu['menu_slug'], 
    array(self,self::load_view($menu['function'])), $menu['icon_url'], $menu['position'] ); 
    self::load_page($page);
}

protected static function load_view($view)
{
    if ( !current_user_can( 'activate_plugins' ) )  {
        wp_die( __( 'You do not have sufficient permissions to access this page.' ) );
    }
    //The actual page to display
    include_once($view);
}

protected static function load_page($page)
{
    add_action( 'admin_print_styles-' . $page, 'admin_styles' );    
}

}

Thanks peeps

3
  • Are you calling this from a plugin? Has WordPress been loaded? Commented Oct 22, 2015 at 19:08
  • Where and how do you initially call add_menu() from your class SetupAdminMenu? Commented Oct 22, 2015 at 19:46
  • I've broken the plugin up into classes, add_menu() is called from outside the class a "controller" fi you would like to call it that which will put the admin menu together. the details $page_title, $menu_title, $capability, $menu_slug, $function, $icon_url, $position are allocated as an array which add_menu($menu) will hand to load_menu()` after wp's add_action() is called to create the menu. Don't know if that makes sense. Commented Oct 23, 2015 at 4:43

2 Answers 2

2

Couple of things going on here. First to just clarify, add_menu_page is to add an administration menu page for managing settings, etc.

Your add action should be as follows:

public static function add_menu($menu)
{
    add_action('admin_menu', array('SetupAdminMenu', 'load_menu'));
}

The way WordPress handles actions requires you to format your add_action as follows for static class methods:

add_action('admin_menu', array('ClassName', 'methodname'), $priority, $numVars);

There are two optional variables:

  • $priority = integer, If there are multiple actions to a hook, the priority will determine the order of load. Default is 10. Use 99 if you want to react to any earlier actions, use 1 if you want to define things before further actions
  • $numVars = interger, if the method or function requires more then one variable, put the number here. WordPress core hooks don't require this to be defined and will pass variables according to the documentation.

Next, the class method with "add_menu_page" is pretty off. To my knowledge admin_menu hook does not return any variables by default and even if it did, why do you want the existing menu when trying to add new items? You pass those variables yourself:

public static function load_menu()
{
    $page_title = 'My New Page';
    $menu_title = 'New Page';
    $capability= 'manage_options'; //An administrator only capability
    $menu_slug = 'my-new-page';
    $callback = array('SetupAdminMenu', 'load_view');
    $menu_icon = ''; //use default
    $menu_position = 81 //After settings

    add_menu_page( $page_title, $menu_title, $capability, $menu_slug, 
    $callback, $menu_icon , $menu_position); 
}

Your self::load_page($page); is redundant. The action you use in that function does nothing. The callback is what is displayed when the menu item is clicked. No reason to make that protected, it would likely fail anyway because of the way class methods are called from hooks within WordPress.

public static function load_view() // Removed $view because you need to define this yourself.
{
    if ( !current_user_can( 'activate_plugins' ) )  {
        wp_die( __( 'You do not have sufficient permissions to access this page.' ) );
    }
    //The actual page to display
    //include_once('/path/to/your/template'); 
    //which should have php, html for what you want to have appear. 
    //To test that the rest of the code is working... just put:
    echo 'Hello World!';
}

This link has a list of a bunch of "how tos" on WP Plugin development.

Sign up to request clarification or add additional context in comments.

2 Comments

thanks for trying to help. your example works @Practically, but that is how I started by doing it in the procedural manner, which I'm not trying to do for readability and for ease of use. my class should be able to "dynamically" load the menu and submenu's. which is what I have trying to achieve the load_view() will call load_page() to the load the admin css on each menu page (I didnt include the function because its not my focus), as is best practice according to the wp codex and in one of the links you posted. I'll get it somehow and post once I do. thanks again.
What I showed above is OOP. If you want to load CSS, then you should do it within the menu page's callback as that is what is called when that menu page in question is loaded. Use wp_register_style there. It is technically possible to manually add styles outside of WP's designed method using the action hook you have, but pointing to an actual function.
0

alright, so I've done some more reading and playing and below is my answer, might help some.

class SetupAdminMenu {

private static $menu = array();

public static function add_menu()
{
    add_action('admin_menu', array('SetupAdminMenu', 'load_menu') );
}

public static function add_sub_menu()
{
    add_action('admin_menu', array('SetupAdminMenu', 'load_sub_menu') );
}

the method below is what I was missing initially, because you cannot pass an argument from the call back in add_action()

public static function setupPage($params)
{
    self::$menu = $params;
}

public static function load_menu()
{
    $page = add_menu_page( self::$menu['page_title'], self::$menu['menu_title'], self::$menu['capability'], 
    self::$menu['menu_slug'], array('SetupAdminMenu', 'load_view'), 
    self::$menu['icon_url'], self::$menu['position'] ); 
    self::load_page($page);
}

protected static function load_sub_menu()
{
    $page = add_submenu_page( self::$menu['parent_slug'], self::$menu['page_title'], self::$menu['menu_title'],
    self::$menu['capability'], self::$menu['menu_slug'], 'load_view');
    self::load_page($page);
}

public static function load_view()
{
    if ( !current_user_can( 'activate_plugins' ) )  {
        wp_die( __( 'You do not have sufficient permissions to access this page.' ) );
    }
    //The actual page to display
    include_once(self::$menu['page']);
}

protected static function load_page($page)
{
    add_action( 'admin_print_styles-' . $page, array('SetupAdminMenu', 'admin_styles') );   
}

public static function admin_styles()
{
    wp_register_style( 'admin_styles', plugins_url('css/admin.css', __FILE__) );
    wp_enqueue_style( 'admin_styles' );
}

}

because add_action() is used so many times I've removed add_menu() and add_sub_menu() from this class and added the method below to may base class to be called with the necessary parameters for any actions

public static function addAction($action, $callback)
{
    add_action($action, $callback);
}

might not be 100% the best way to do it yet but the above currently works.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.