In my experience, the way we first interact with the repository design pattern often influences how we think about the pattern. (The whole first impressions are lasting impressions, right?)
The purpose of this post is to show how it can be implemented in WordPress specifically when writing object-oriented plugins to read data (writing data may be covered in another post), but before doing that I tried to think of a few consistencies among the variations of the pattern that I’ve seen.
Generally speaking, this is what I think a repository pattern should do:
- provide a single place to read data,
- abstract the details of how the data is accessed,
- and have a consistent interface for doing so.
This means that whatever it is you need to retrieve from the application can be retrieved from the database. But how its retrieved can be considered a black box. That’s up to the developer implementing the pattern.
And in the case for those who read this post, that’s most likely us.
The Repository Pattern in WordPress
A couple of years ago, I wrote about the repository pattern giving a concrete example. It’s still relevant, but the purpose of what I want to cover in this post is a bit different.
Rather than showing a particular implementation rooted in an actual example, I’d rather make a case for how we can employ this pattern in our day-to-day work.
The two things to keep in mind when reading this are:
- from the user’s perspective, the underlying data-store doesn’t matter,
- from the developer’s perspective, the pattern allows us to work with multiple data sources and also mock up a sample data store so we can unit test the data.
When implementing the pattern, where the data comes from doesn’t matter. At least as long as you’re the developer or client object calling into it. The data store can be a database, a set of API functions, or a combination of both.
Let assume, then, that you’re working with a custom post type for Events and you’re also working with post metadata and options related to something like events.
You may way to do something like:
- get the name of the event,
- find information about the location of the event,
- retrieve the first post type and status ordered by its ID
All of this information can be scattered in different places and how it is retrieved can vary.
1. Getting the Event Name
If we’re working with a custom post type and we need to get the event name, then we can use a post’s ID and one of WordPress’ API functions to do it.
This is one case in which the data store is still abstracted away from us and, instead, leverages the existing WordPress API.
2. Getting the Event Location
In this case, we can assume that the event location has been manually entered or perhaps been retrieved by a third-party API. And since the location is associated with a specific event, then it may be in the post metadata table.
Again, we can retrieve it using pre-existing API functions; however, in situations like this, it makes sense to have a helper function because we’ll likely be accessing other metadata, too.
So first, the helper:
And then the function that uses the helper to get the location:
But in these two examples, we’re still using existing API functions. What about the case where we need to talk to the database?
3. Retrieving a Single Post URL
In this case, we’re going to be communicating directly with the WordPress database. If you’re familiar with the $wpdb object and SQL then this won’t be a big deal.
Given this, we can write a query that will do the following:
- grab all of the posts where the ID match a certain value, the post type and the post status are a certain value, and we’ll order the results by ascending value of the ID,
- next, we’ll use the results of that query to get a single value.
And we can do this by both accessing the database and writing a nested query:
And then all of this can be encapsulated in a single class which would be, say, the Event Repository (or EventRepository).
I’ll have more about this in a follow-up post, though. Namely, how to handle determine what functions belong where, the naming conventions, and how to handle persistence should you want to introduce that into your repository, too.
Above all else, keep this in mind:
The repository pattern masks how the data is retrieved but provides a consistent way for how the data with which it’s related can be retrieved.
Some may also add how it can be retrieved and how it can be written, but perhaps I’ll discuss that in another post.