1

I'm working on a plugin.I've created a new menu entry inside my functions.php. The basic idea will be to have a default menu which will be the parent of several, small and different plugins.

I have pretty much all in place, but I have an issue when I click on the plugin submenu entry.

The URL is broken, and instead of going to the right admin page

http://localhost/wp-admin/admin.php?page=my_page

it goes to a frontend page, which is not available and so it goes on 404. The broken URL looks like this:

http://localhost/wp-admin/my_page

As you can see, admin.php?page= is missing from the second entry.

I've investigated a bit and it looks like this is fixed if i initialize the menu from the plugin itself, rather than the functions.php file.

Some code to prove it:

WORKING

public function add_menu_item()
{
        $page_reports = add_menu_page(__('Menu Page', 'menu-page'), __('Menu Page', 'menu-page'), 'read', $this->parent->_token . '_settings', null, null, '2.1');
        add_submenu_page('menu-page', __('Report', 'menu-page'), __('Report', 'menu-page'), 'read', $this->parent->_token . '_REPORT', array($this, 'IncludePluginPage'));
}

public function IncludePluginPage()
{
    include("../includes/index.php");
}

NOT WORKING

public function add_menu_item()
{
        //$page_reports = add_menu_page(__('Menu Page', 'menu-page'), __('Menu Page', 'menu-page'), 'read', $this->parent->_token . '_settings', null, null, '2.1');
        add_submenu_page('menu-page', __('Report', 'menu-page'), __('Report', 'menu-page'), 'read', $this->parent->_token . '_REPORT', array($this, 'IncludePluginPage'));
}

public function IncludePluginPage()
{
    include("../includes/index.php");
}

// Code from functions.php to generate the menu entry

function custom_admin_menu(){
    add_menu_page('Menu Page', 'Menu Page', 'read', 'menu-page', null, null, '2.1');
}

In both cases, the menu is correctly displayed, but when the menu is initialized from functions.php, the submenu URL is broken.

What am I missing here?

Please feel free to ask for more code, I wasn't really sure what to add in here to be as much help as possible.

In case you're wondering, I started from this template here: https://github.com/hlashbrooke/WordPress-Plugin-Template

1 Answer 1

2

The menu is generated by the function _wp_menu_output. If you look at the place where the links are generated (currently lines 158-162 and 170-174) you see that the admin.php?page= part is omitted under certain circumstances. One of those is an empty $menu_hook.

The variable menu_hook is filled by a call to get_plugin_page_hook, which will return empty if no action is bound to the hook. This translates to: there is no callback function defined to generate the page.

Now let's look at the hook order: plugins are loaded before themes, so if you generate the submenu before the parent menu (which you do if you initialize the parent menu in the theme's functions.php) there might be a problem at line 190-192 of add_submenu_page: it might not be possible to bind an action to the hook at that point because the parent page is undefined.

Disclaimer: I analysed the code from the top of my head, so I may have made a mistake there.

Anyway, if you insist on initializing stuff from your functions.php, don't try to initialize the submenu in your plugin. Instead just define the function in your plugin and call it from the theme as well.

Your Answer

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

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