Partials in WordPress, regardless of if they are part of a plugin or part of a theme, can help maintaining a project much easier (let alone building a project).

But if you’re working with them to help drive your settings pages or your WordPress administration pages, part of working with them is making sure they are adequately represented on the server-side, too.

Generally speaking, this is usually referred to as the domain logic or may even be thought of as part of the “model” or “controller” code when thinking regarding MVC. Of course, this isn’t MVC, and I’m no fan of trying to apply patterns where they don’t fit.

My point, though, is that I’m talking about object-oriented classes that are responsible for managing data and handling coordinating information rendered in the partials and how the user interacts with it.

Writing Classes for Partials in WordPress

In yesterday’s post, I shared why I’m a fan of separating administration pages into partials (largely because of maintenance). But one of the things I didn’t talk about was how I approach handling the server-side or the back-end of the partials.

At first, I think it’s common to want to create a class for the “Dashboard” or the setting pages or whatever you want to call it. For this post, I’m going with Dashboard.

The design may look like this:

Object-Oriented Partials in WordPress: A god-class.

You’ve got one large class responsible for coordinating information for all of the options the user sees. Given what all a page that features options requires, this class will likely include functions for each option, validation, sanitization, security functions, helper functions, and so on.

It can get really big, really fast. And in doing this, it loses the idea of having a single job or a single responsibility and ultimately becomes a glorified collection of functions thrown into a class that doesn’t represent object-oriented programming at all.

So all of that maintainability we’ve aimed for with breaking a template into partials is somewhat compromised because the server-side code doesn’t model what’s happening in the view.

There’s no parity.

That shouldn’t be the case, should it? I mean, if the front-end has a relationship to the back-end and we’re aiming for maintainability, the object model should correspond to what happens on the front-end.

And by this, I mean that there should be classes specifically designated for each partial.

This means that the Dashboard class can house all of the functionality responsible for driving the user interface at the highest level such as handling nonce validation and data serialization. Then, there can be classes for each of the partials that house functionality related to that partial.

A simple version of this idea may look something like this:

Object-Oriented Partials in WordPress: Partials

This means that the partial can call into its corresponding class file when it needs to retrieve something, or it can pass information into one of the functions when it needs to have it parsed, saved, or something else.

Ultimately, the server-side code now models the view, and there’s less responsibility for each class and tighter cohesion between the back-end and the front-end.

Is There a Design Pattern for This?

In a classic non-answer, yes and no.

There are ways in which you can go about organizing this such that when you start the plugin, everything is instantiated and then the partials are aware of the classes driving them and the classes are aware of the main dashboard class.

But how we achieve this can vary.

Some may opt to try to create subclasses of the Dashboard class, but this can cause problems when the partials try to call into it because they have to know more information than necessary.

Another way may be via dependency injection where you can take the classes that drive the partials and then inject the main Dashboard class into them via, say, their constructor. But then WordPress still needs to be able to call a method on that class to display the partials.

Or perhaps you create an interface or an abstract class and have the necessary class implement the functions necessary. This approach, though, may end up with you having multiple classes declare abstract function names to satisfy the requirements of an interface. And this can defeat the whole purpose.

Obviously, there are options, and each of them has their tradeoffs. I’ve not listed all possible ways, either. Instead, I’ve listed some of what I’ve seen and some of what I’ve tried.

Given all of the above, what’s the best approach you’ve tried or what way do you consistently use when working with this kind of architecture? I’m legitimately curious because I’ve yet to find one that I like.

Though I do think anything is better than a god-class and a god-template, I’ve yet to be satisfied with one way I’ve tried.

Category:
Articles
Tags:

Join the conversation! 5 Comments

  1. Hey Tom,

    I have not finished my WP Settings API subsystem yet, though it is already usable (and used in small and large sites).

    The basic way I’m dealing with this right now is to have a Settings class (https://github.com/brightnucleus/settings) that gets a Config file with a tree of pages/sections/fields. The Settings class is responsible for going through this tree and building the corresponding objects/data fields.

    Right now, each page/section/field is associated with a View. My next iteration will have standard views included for each of the prebuilt types, so that you only need to define the data type for all of this to just work, but you can optionally override every single element with a custom (templated) view.

    Thanks for letting me notice now that I have not yet written any documentation for the brightnucleus/settings package! :)

    Cheers!

    • Your timing on this comment is eerie. I’m working on a client project right now where the current Settings API is something that I’m opting not to use for a variety of reasons (despite the fact that I usually push for using as many of the native APIs as possible).

      What you’ve said sounds like we’re facing many of the same issues. The short of it for me is that I’ve got my display separated into partials and each partial is backed by its own class that’s responsible for coordinating information from a WordPress-layer to the view and back.

      Ultimately, it’s allowing me to create lighter-weight unit tests by just testing the layer sitting between the WordPress communication layer and the view without having to load up the entire application to do it. I’m really please with it so far.

      Anyway, more to respond to…

      I have not finished my WP Settings API subsystem yet, though it is already usable (and used in small and large sites).

      Mine is being written specifically for a multi-month project that’s specific to one of my clients. I’m really enjoying writing it, but it’s also exposing some neat technical challenges. 

      The basic way I’m dealing with this right now is to have a Settings class (https://github.com/brightnucleus/settings) that gets a Config file with a tree of pages/sections/fields. The Settings class is responsible for going through this tree and building the corresponding objects/data fields.

      Okay, this is neat because I have something very similar set up. I don’t have a config file because I have each partial having its own class where the class maintains a data structure of the options on the view.

      This allows me to handle serialization and validation for that particular partial and work on it independent of the entire admin view without having to deal with this huge, say, ‘Dashboard’ class. Instead, I can just work on the ‘Import’ view or the ‘User’ view (not to be confused with the WordPress users screen.

      One technical hurdle that I’m trying to work through is if the main settings class should be aware of the smaller, partial-specific classes. Should they be subclasses, should there be a Service class coordinating information (this is something Tonya and I were talking about), etc.

      Right now, I’m not too worried about it, but it’s in the back of my mind.

      Right now, each page/section/field is associated with a View. My next iteration will have standard views included for each of the prebuilt types, so that you only need to define the data type for all of this to just work, but you can optionally override every single element with a custom (templated) view.

      Mine is basically:

      Settings class handles information at the high level. Security validation, nonce verification, and then writing the arrays to the options table.
      Each view has a class that corresponds to it that’s responsible for helping pump data into the view and then properly structure and sanitize it then pass it around to be saved.

      I’m saving all options in a single, serialized array because this happens to map well with how the controls are set up.

      I generalized my functionality for sanitization just last night so that it can be used for any view, but the views only use a subset of controls that we’re used to seeing and the rules are specific to the business domain in which I’m working hence I wouldn’t roll it out for anyone to use.

      Thanks for letting me notice now that I have not yet written any documentation for the brightnucleus/settings package! :)

      Of all my development-oriented things, this is the one I’m best at ;P.

  2. I don’t have a config file because I have each partial having its own class where the class maintains a data structure of the options on the view.

    I try to avoid such systems, because of testing reasons. I tend to write my classes in a 100% reusable way, with every project-specific stuff going into Config files. This allows me to reuse these classes as they are in my next project (pulling them in through Composer), thus starting a brand-new project from scratch with half of the entire project already covered by unit tests.

    If you write a specific class for each use case (instead of a generalized class, that handles each use case through configuration), you’ll need to write new unit tests for every single one of them. (well, or you don’t….)

  3. I agree with Alain about moving project specifics to a “configuration architecture”, where project uniqueness belongs to the Config. The advantages here are many including testability, modularity, reusability, and abstraction.

    The Settings class is the API handler acting upon the specifics injected via the Config. This allows the Settings class to focus on the actual API handling tasks and not the project’s implementation.

    You can then reuse the Settings class for any project. Just define what you need by loading in the desired settings configuration, defaults, and specific view. Make it adaptable for specific business logic needs for making decisions based upon the project’s specific values and needs.

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.