Assuming you’ve read the following two posts (on the single responsibility principle and WordPress submenus), then this is a good place to tear apart the code and start trying to apply the principle.
If on the other hand, you haven’t read the posts, there are two things to note. First, the single responsibility principle says the following:
A class should have only one reason to change.
Secondly, review the code in this gist as this is the basis for the rest of the content of this article. Specifically, I’m going to be taking the above principle and try to apply it to the code.
Single Responsibility Principle: Options Pages
Anyone who has worked with the WordPress API to add a submenu item to the existing WordPress menu likely knows that for each submenu item, there is an associated options page.
In fact, the API function requires a function to render said options page as one of its parameters. The description of the last parameter says:
The function to be called to output the content for this page.
If a class should have only one reason to change, then it’s reasonable to look at the existing code and ask: “What is the reason (or what are the reasons) this class may change?” And looking at the code as it stands, I can see at least two reasons:
- The submenu item text or attributes need altering,
- The display of the options page needs to be modified.
Already, we have two reasons this class may change. This shows that there’s potential for separating this class into two classes. Given one reason the class may change is that of the submenu item and the other reason is that the options page needs to be modified, the code can be separated such that we have a class for each.
That is, we can create a class for the submenu and a class for the for the options page. There are a few ways to do this, but the approach I’ve been taking (which is always likely to change) has been to do the following:
- Create a class for the Submenu,
- Create a class for the Options Page,
- Add a property to the submenu so that it’s aware of the options page (since it has to invoke the function for rendering it),
- Add a property to the submenu page such as the array of options it’s responsible for rendering, saving, deleting, and so on.
With that said, the submenu may look something like this:
The options page may look something like this:
And then you’d instantiate the
Submenu by passing the
Options_Page in as a parameter:
Ultimately, this separates the submenu from the options page. There is still a dependency between the two classes, but I think that’s okay since the submenu needs to be aware of the page it’s responsible for rendering.
Regardless, this separates the responsibilities of each class, makes each more testable (especially the Options Page class), and makes the code a bit more maintainable.