An MVC-like WordPress Development with ACF and Timber

Improve your WordPress themes with ACF, Timber and a grain of inspiration from the MVC pattern.

You would expect that because WordPress is so popular, WordPress theme development would be easy. In fact, it can become quite messy especially for beginners. Why is that?

The official Theme Development Standards and Twenty themes promote fetching and displaying data in the same place. They don’t encourage separating core site functionality to a plugin. So what you usually end with are templates with cryptic loop constructs and gigantic functions.php file. In this tutorial, I’ll show you how you can make your themes cleaner by borrowing some development principles from the MVC (Model-View-Controller) pattern.

Let’s make it clear, WordPress is not an MVC framework; it implements the event-driven architecture. However, we won’t be making it to what it’s not; we’ll be just loosely thinking about our application parts at they were separated to Model, View, and Controller.

Sample Site: Dream Team

Here’s the app, we’ll be building – a Dream Team site! Click on the images to see its live preview.

Dream Team site: Team List

Dream Team site: Person Detail

The site has two primary type of pages:

The team list page with persons’ names and images linking to person detail page

The person detail page with the following data

photo

name

position

description

quote

a list of blog posts by the person

a link to interview with the person

links to display a previous/next person

Additionally, we can display individual blog posts.

Setup: Chisel

To start with the development, we will install and setup WordPress with Chisel, a Xfive tool for easy installation and development of WordPress projects. Chisel installs Timber automatically and allows us to install ACF too.

If you haven’t worked with Chisel, install Node.js and then run from the command line:

Select WordPress with Front-end project type and enter your WordPress configuration details once you are prompted to do so. Don’t forget to choose ACF plugin.

WordPress setup with Chisel

Once the installation is complete, run Gulp command:

gulp

to start a Browsersync server which proxies to your WordPress instance.

Model: ACF and WordPress

Model in MVC represents data and relation among them. What data have we got in our Dream Team app? WordPress comes with built in data like blog posts, pages or comments but since these data are already modeled, they are not our concern.

What is unique to our application (our problem domain) is Team, more specifically a Team Member, because the Team is just a list of team members.

To define new data type in WordPress we will use a custom post type. To make our application more manageable we will define Team custom post type in a functionality plugin:

Get the whole functionality plugin from this repository. Place it in the wp-content/plugins directory and activate in the WP admin.

Next, we will use ACF plugin to model the team member according to our application requirements. We know that he or she has the following characteristics:

photo

name

description

position

quote

interview

list of articles

Note: You should be able to follow this tutorial with a free version of ACF, but a Developer license of the PRO version is worth of investment for any developer who makes a living out building WordPress themes.

If you have checked the functionality plugin code, you could notice that we have fields already available for the photo, name, and description. These are regular post title, featured image and content which we enter into the editor field. We don't have to create fields for these, but we could if we have not enabled them in the custom post type definition.

To create remaining fields go to Custom Fields / Fields Group and Add new. Name it Team and add the fields as follows:

Adding custom fields with ACF

Let’s explain what’s going on here:

First of all, we show this field group on our custom post type Team Member.

For the position, we choose type Taxonomy so we can add and manage positions easily. To do this, we will get back to our functionality plugin and register taxonomy there. Check out the file here.

Then we can select which taxonomy should be displayed:

ACF: Taxonomy setup

The Quote field is just a simple text area.

The Interview will be a blog post with an interview with the person. We can limit this field to the post type post and category Interviews if we have created such category for our blog posts.

ACF: Filter by post type and taxonomy

Finally, we need to ensure that we can display a list of articles written by a team member. To do this, we associate a team member with a WordPress user who can write blog posts.

This setup is suitable when we have many team members from whom only a few are authors, so we don't want to create and manage WordPress user accounts for all team members.

Of course, if all our team members are authors too, we could add the field group to the form for adding WordPress users. In such case, a rule for displaying the field group would be Show this field group of User form is equal to Add / Edit.

Now we can add some data in WP admin. Go to Team / Add Team Member and add a few team members. Create WordPress users for some of them, so they can publish articles.

Controller: WordPress and Timber

Once we have our data modeled and created, we will take a look at the controller part. The controller in MVC routes requests to our application and take care of getting data from the model and sending them to the view for displaying.

In WordPress, the template hierarchy determines how requests are routed. We will use Timber to get data from the model and send them to the view.

We will have two controllers:

team page index

team member detail

You can create Team page with Chisel command.

yo chisel:page "Team"

This will create a Team page and also its Twig template in templates/page-team.twig. Rename this to team.twig to match the PHP file we will create shortly.

Make the Team page the front-page in WordPress admin - go to Settings / Reading, select Front page displays: A static page and select the Front page: Team.

Then create PHP template team.php which we will use as a controller and enter the following code to it:

What do we do here? First, we get context which is a Timber object storing various common data needed across the site. The context already contains the post data because it was globally added in functions.php. Then we get all team members. We assign this newly acquired data to the context variable so we can pass them to the view in the last step.

Finally, select template Team for the page Team in the WP admin.

Setting up Team template

For displaying team member detail, we will create new PHP template single-team.php. WordPress will automatically route requests to /team/[slug]/ to this template and allow us to get a proper team member.

As you can see, displaying data is pretty self-explanatory, just remember what type of data is that. For example, the post is a Timber\Post object. Refer to documentation to see what properties and methods the particular object has. Here we could easily retrieve prev and next links with the built-in methods.

Conclusion

In this tutorial, we have shown how we can better organize our themes by borrowing some principles from the MVC pattern. To achieve this, we have used two powerful WordPress libraries - Advanced Custom Fields and Timber.

By thinking about our application in terms of MVC, we can focus on each concern one at a time - modeling data and relation among them in the model, routing requests and getting data in the controllers, and finally data presentation in the view. Splitting WordPress theme development this way makes it faster, more flexible and resulting code easier to maintain.

I would also add VVV initialization scripts to the mix and replace Browserify with webpack (much easier to handle than browserify with gulp)

At some point you have to ask yourself though, why you stick with Wordpress and not switch to a real MVC like laravel. I'm not hating, you can morph wordpress into a modern looking dev-dream, but at some point you will have to work with the bad parts, the API, Core, Documentation, Insecurities and Database Issues of wordpress...
Once you make the switch, you'll never look back :)

Lubos Kmetko•
February 17, 2017

Thanks, Flo, good to hear :) Thanks for the VVV and Webpack suggestions, that's definitely something on our radar for the future.

I understand your point about switching to a different framework which doesn't have so many limitations and issues since start. Yet, there is still something quite appealing at WordPress, which makes us return to it :)