Thoughts on WordPress and the MVC pattern

Getting proficient with object-oriented programming can feel like falling down a rabbit hole. You break down problems into more and more classes. You feel like it’s neverending and that you could go on forever. You need guidance to make sense of it all.

This is where architectural patterns come in. They’re similar to software design patterns which you use to solve a specific problem. In contrast, you use an architectural pattern to address a set of them at once.

This confers certain benefits to architectural patterns. You get a higher level view of how your classes interact with each other. You then have an easier time piecing everything together.

This is why it’s not uncommon for developers to skip over software design patterns. Instead, they start looking into architectural patterns right away. This is even something I’m guilty of doing (insert audience gasp).

One of the most important architectural patterns is the “model-view-controller” (known as MVC). It’s used by most modern frameworks from Rails to Angular. But does it have a place in WordPress?

So what is the MVC pattern?

The MVC pattern divides your application into three broad components: Models, Views and Controllers. These three components manage the interactions between your application and the person using it. The pattern also defines how component types communicate between each other.


When a person uses your application, he interacts with a Controller through the View. That Controller makes changes to a Model. In a lot of MVC implementations, it’ll also control the content of the View.

The Model is where all the data and business logic of your application lives. The Model manages all that information. The Model might notify the Controller or the View when there’s been a change. Or it might expect them to ask it for that information. Again it varies from implementation to implementation.

The View has a simple role. It’s the component in charge of what the user sees. It takes care of the display of the information in the Model.

History of MVC

You might not know this, but the MVC pattern is old. Not old in Internet time (which is what? 10 minutes?), but “old” old. Most of us weren’t born when computer scientists invented it. It was key to the creation of the graphical user interface at Xerox Parc.

The pattern evolved a lot since then. There’re a lot of variations out there. That’s something that you could see with the definitions of the components. The web development world has also embraced the pattern. A lot of the most popular web frameworks use it.

All this popularity has consequences though. The definition of the pattern weakens as more people use it and change it to fit their needs. We call that “semantic diffusion“. It’s a term that Martin Fowler coined to explain that phenomenon.

How does it fit in the WordPress world?

There’s a long history of developers implementing the MVC pattern in WordPress. None of these attempts yielded something used by a lot of WordPress developers. Why is that?

It goes back to this idea of semantic diffusion. Each attempt took the MVC pattern and tried to shoehorn it into WordPress. They didn’t take in consideration how WordPress works. It isn’t something that you can neglect or ignore.

The arrival of the WP REST API highlights this even more. It’s a significant transformation with a lot of implications. It’s changing how you can work with WordPress. When thinking of MVC pattern, you have to consider two realities now:

  1. MVC on the side of the browser where WordPress is only a data source.
  2. MVC on the side of the web server where you install WordPress.

The browser reality

The MVC pattern makes a lot of sense in the browser. A browser application has a lot in common with the desktop applications of old. It’s reacting to a variety of external events. You’re clicking on things, entering data, receiving data, etc.

Your application needs to handle them all. That isn’t a problem for the MVC pattern though. It’s in those types of situations that it shines most. That’s why it was created after all.

There’s another important fact that you need to keep in mind. It’s that it’s not WordPress that’s trying to implement the pattern. It’s the JavaScript framework that you decide to use that does this.

WordPress is only the data source used by the Models. There’s no need to shape WordPress core into an MVC framework.

The web server reality

You can’t say the same about what goes on the web server. It’s quite different. A server-side application like WordPress doesn’t deal with a lot of external events. It’s reacting to an HTTP request made to the web server. The application converts that request into an HTTP response. The web server then sends it back.

This dynamic hasn’t prevented other frameworks from using the MVC pattern though. Why couldn’t WordPress do it too? It’s just not that simple. You can’t wave a magic wand to implement the MVC pattern (I know… what a bummer).

The creators of those frameworks designed them with MVC in mind. They didn’t think, “Ok done! Now I’ll just slap the MVC pattern on this baby and we’re good!”. No, it happened from the ground up.

This wasn’t the case with WordPress. We could try to guess why that is, but the reasons aren’t all that important. What’s important is accepting that reality.

And that reality is that WordPress core is a poor fit for the MVC pattern.

The WordPress reality

So what’s a better fit than the MVC pattern for WordPress? Let’s take a step back before we attempt to answer that question. Let’s try to look at the larger picture and ask yourself these questions:

  • Is it possible that this isn’t only a WordPress problem?
  • What if the MVC pattern is a poor fit for most web applications as well?
  • If that’s the case, what’s a better way to describe what goes on in a web application?

You can’t google answers to these questions (aww crap). There simply are no answers to them (yet). That hasn’t prevented people from thinking about them.

ADR: Rethinking MVC for the web

One such person is Paul M. Jones (a real smart cookie in the PHP world). He’s been working on a web-specific refinement of the MVC pattern. He calls it the “action-domain-responder” pattern (or ADR for short).


It’s an attempt to better represent how we work with a web application every day. It goes back to how we described it earlier. The essence of a web application is to convert an HTTP request into an HTTP response. The ADR pattern embraces that idea at its core.

Differences between ADR and MVC

Let’s take a look at what distinguishes the ADR pattern from the MVC pattern. We’re going to keep this high-level and only discuss their components. You’ll get a good picture even if we don’t go into the technical details.

Domain vs Model

Both the Domain and the Model manage the data and business logic of a web application. The main differences between the two come from how they interact with other components.

Let’s look at the Model in the MVC pattern. It’s free to send information back and forth between the View and the Controller. The relationship between the three isn’t a rigid one.

In contrast, that relationship in the ADR pattern is quite rigid. Only an Action can change the Domain. The Responder only uses the information from the Domain. It turns that information into a response to send back. That’s all.

Action vs Controller

In a lot of MVC implementations, the Controller is just a wrapper class for a set of actions. These actions are often just methods inside that class. Its also offers some common logic and helper methods for those actions.

The ADR pattern abandons the notion of Controllers. Instead, it focuses only on the concept of Actions. An Action is a unique operation performed by the web application.

When the application receives a request, it forwards it to the matching Action. This means that you can’t have more than one Action for the same request. That’s why an Action is unique.

The Action does its task (like creating a post). It makes the necessary changes to the Domain. Once it’s done, it’ll pass that Domain data to the Responder. That’s it.

This highlights the differences between how the different components communicate. An Action interacts with the Domain the same way the Controller and Model do. They’re both free to make changes to the Domain or Model.

The difference is between the View and Responder. A Controller can interact with the View. An Action only hands over data to the Responder, but it doesn’t change it.

Responder vs View

The View and the Responder are where these two patterns differ the most.

For the MVC pattern, the View acts as a “content generator” for the Controller. It’s often nothing more than a template. The Controller uses the View to generate the content of the response. Using that content, the Controller creates the complete response for the web application.

In that situation, the Controller is stuck doing a lot of the presentation logic. It needs to set response headers. It needs to handle different content types (e.g. JSON and XML). The result is that the Controller ends up doing too much and the View too little.

The design goal with the Responder is to take some of these responsibilities back. The Action focuses on performing making changes inside the web application. The Responder crafts the response that it sends back.

This means that the Responder needs to take care of any task needed to generate a response. These include tasks like:

  • Setting the proper response headers.
  • Selecting the content type of the response.
  • Creating the content of the response (using a template if needed).

Those are some of the obvious ones. What matters is that a task fits the mission of the Responder. And that’s to tailor the response from the web application.

ADR and the WordPress reality

Well, that was a lot of explanation! At this point, you’re wondering, “How does ADR apply to our WordPress reality?”. Let’s discuss why that is.

A Domain in WordPress?

Creating Domain (or Model) classes isn’t something that you do in WordPress. Sure, you might see someone using an ORM library. That’s more of an exception though.

Most of us just deal with posts and custom post types. WordPress has the WP_Post class, but that’s it. There’s nothing else to use.

Don’t despair though. It doesn’t mean that you can’t create Domain classes. It is possible. You can even do it without an ORM library.

The key is to design with that idea in mind.

Action and the plugin API

The concept of Action and Responder also makes more sense for WordPress. WordPress doesn’t mix presentation logic with application logic. In its eyes, they’re two separate systems that (more often than not) don’t interact with each other.

The plugin API is there for you to add application logic to WordPress. It’s how plugins (and themes) change how WordPress behaves.

You know what it doesn’t do? It doesn’t handle how WordPress generates its response or its content. It’s just a mediator that can change it.

If you think about it that way, it does sound a lot like an Action. An Action could just be a class that groups plugin hooks together. Together how? Well, it could group them around that unique operation we discussed earlier.

We’re just brainstorming here. It won’t be THAT simple in practice. The point was to show that the concept of Action makes sense in the WordPress reality; more so than a Controller.

Responder and the WP REST API

What about the Responder? How does it fit? It’s easier to explain that one. It already exists in WordPress.

In WordPress, template-loader.php is the main file in charge of the presentation logic. It handles content generation by loading the selected template. It can also perform redirects using the template_redirect hook.

That hook can do a lot more than redirects though. The comment next to it says it best: “Fires before determining which template to load.”. It’s the last hook before WordPress switches to templates to generate its content. It’s the ideal location to add a Responder.

In fact, that’s what the WP REST API does. It uses that hook to create a response and send it back. It’s doing something like a Responder.

That’s the important point to take in. You could create a Responder and attach it to the template_redirect hook. The WP REST API shows that it’s possible.

Time for a WordPress ADR framework!?

Slow down grasshopper! The need for a framework is a different discussion. It wasn’t what this article was about. This is a taste of what high-level design feels like.

As you saw, design isn’t an exact science. It’s a discussion around the reality that we live in. It’s an attempt to build something around the constraints of that reality.

Architectural patterns are great for that as long as they fit that reality. They give you a way to describe it from a design perspective. You get a better view of what you’re building.

Things get hairier when you get off the beaten path. This high-level view can get dizzying when exploring new ideas. It means you have more moving pieces to keep track of. It’s a worthwhile tradeoff though.

At the end of the day, you get to design and build classes that feel meaningful. And that’s nothing to sneeze at.

  • Excellent article! I would argue that the main problem of WP not following MVC isn’t architecural/design. The problem is many developers learn to code after they have been using WP for some time. And since most plugins don’t follow *any* kind of patterns, the code ends up being procedural, wothout any clear separation of concerns or logic. And the technical debt just grows. Because backwards compatibility.

    • No, they don’t, but I can’t fault them too much on it either. WordPress is a legacy piece of software that predates OOP in PHP. The issue is that new code being added is also mostly procedural. The classes aren’t reusable by plugin developers anyhow.

      So you can teach them about it. The issue is that there’s no advantage. WordPress gives them almost no tools to leverage.

      I think the technical debt is an issue in the long run. I think you can overcome it while maintaining BC. It also depends where they set the limit for BC.

      The APIs are good facades. You can build something good behind them. If you have to maintain the use of global variables, that’s a larger issue.

      In the end, you have to live with the systems as they’re currently designed. You have to design your OOP code around them. That’s why I focus a lot of my writing on it.

  • SSDN Technologies

    Amazing. This is Helpfull. Best about MVC.