A WordPress menu page is something that’s easy to introduce thanks to API functions like add_menu_page. On top of that, it’s easy to add submenus using add_submenu_page.

But if you’re working with the plugins_loaded hook or a plugin bootstrap file, then trying to introduce a WordPress menu page (along with any related submenus), you may end up with some unexpected results.

Custom WordPress Menu Page: A reference to plugins_loaded.

The plugins_loaded documentation in the code reference.

Specifically, you may find that your menu and submenus display fine, but they don’t work when you click on them to navigate to the relative page.

A Custom WordPress Menu Page

Say, for example, you’re kicking off your plugin like this:

And then you have a class that represents your top-level menu. And that top level menu refers to two other submenu classes that also represent their page (we’ll call ’em settings and import):

Notice in the code above, I have a constructor which sets its properties based on data it retrieves from a container object. In essence, this container is a poor man’s dependency injection container.

These are not containers you are looking for.

These are not containers you are looking for.

Rather than get into the details of it, simply think of it as a class that holds all classes relevant to the plugin that allows us to access them without creating unnecessary dependencies.

With that said, the rest of this is within an init method, but there’s a problem: When you go to click on the menu items in the WordPress administration area, the menu item nor the submenu items work.

So you try this:

Here, you’re setting up a custom menu page using the WordPress API, but you’re not getting the results that you’d expect.

But nope. It doesn’t work. I mean, it does something, but not what we want. So what gives?

There’s a Catch

In the new-ish WordPress Code Reference, there’s a note later down the page for each for add_menu_page that reads:

If you’re running into the “You do not have sufficient permissions to access this page” error, then you’ve hooked too early. The hook you should use is admin_menu.

In the example that I’ve outlined above, you’re likely not seeing anything about “sufficient permissions,” but you may be finding yourselves landing on a 404 template on the front-end of the site.

But the gist of the problem is correct:

We’ve hooked too early.

So if we’re trying to stick with using plugins_loaded but we want to make sure we’re focused on creating classes that represent our menu, what do we do?

We have to make sure we’re hooking into the proper function. The short way to do this is to update the init method to register a new function with WordPress.

The final version of the code will look like this:

And this will resolve the problem.

More Time? Better Solutions

If you have more time to implement a cleaner solution, then I’d make the case that registering WordPress actions within classes that are solely meant to represent a menu isn’t the cleanest implementation.

Instead, this should happen outside of the class. Perhaps there should be an interstitial type of Registry class that accepts a hook and a method and then registers it with WordPress.

That’s outside the scope of this post, but it’s something to consider.