The single responsibility principle (SRP) tells us that each module, class or even function should have one single responsibility It means that every class, or similar structure, in your code should have only one job to do. Everything in the class should be related to that single purpose. It is a simple and intuitive principle, bu it is sometimes hard to get right.
A lot of us developers seem to have an ill adjusted intuition for when it’s time to restructure our code. It’s far too easy to convince ourselves that we’ll go back and clean up at a later time. I convince myself about that a lot more often than I actually go back and refactor something.
We also seem to have an even worse intuition for what type code code that will be easy to maintain in the long run. A lot of us (again, that includes myself) gravitate towards code that pack too much functionality into one place. We tell ourselves that it’s a quicker way to get the job done.
However, there’s a price to be paid for going to quick at the beginning and that price is almost always that you go gradually slower and slower. The very things we did early on to increase speed has a huge risk of slowing us down in the long run.
The point with the single responsibility principle is to help us get things (more) right from the start. The SRP tells us to take the time up front to design our code in a way that helps us in the long run. Each group of functionality into it’s own encapsulated and isolated class or module. Don’t mix and match apples with rocket ships.
Single responsibility principle leads to Cleaner code
As with many things, you can take the single responsibility too far. It does not mean that your classes should only contain just one method. There may be many members as long as they relate to that single responsibility. It may be that when the a change occurs, multiple member functions of the class have to be updated. It’s even quite likely in many cases.
But the SRP does mean that we should try to separate code that might change for different reasons. A class that could change both because we want to modify front end HTML color scheme OR because we need change authentication method is most likely violating the SRP.
Working with the SRP is likely to have a tremendous effect on your code. You are going to get more but smaller classes in your design. Each of those classes will be a lot cleaner since they’re only concerned with one thing. You’re also going to have to be more diligent with how you name your classes and if you’re OK with letting go of PHP 5.2 (you should) you are going to benefit from using PHP namespaces and folders. You’re also being forced to think more about how each class interacts with the others since everything isn’t just available in the same class or even namespace any more.
A well thought out system design where classes are logically organized in folders and where each class is tightly focused on a single purpose sounds kind of appealing, doesn’t it? It also sounds a lot like what we call clean code.
(and clean code tends to be more testable and maintainable).
Finding the balance: Class Employee
There’s a classical example used to explain the only one reason to change idea, a class used to represent an employee in a system. The questions we’re supposed to ask is if it’s OK to have both functions to calculate the employee’s salary (business logic) and a set of functions that reads and writes employee objects to the database (persistence)?
The answer according to the SRP is no, the employee class should not mix business logic with persistence functionality. There are at least two reasons for the employee object to change, the first reason would be if we want to change the method used to calculate salary. The second reason to change would be if we decided to modify the database schema. Therefore according to the SRP, we should design our system with one class for employee business logic and another class for employee persistence. Different reasons for change means different classes.
But in a WordPress situation you could argue that this is a little bit over the top. Imagine a WordPress plugin that adds the custom post type to implement the Employee object and a third party tool like Advanced Custom Fields to define the various extra fields. We could still split the functionality in to two classes, one for business logic and one for database persistence.
The persistence mechanisms for a custom post type are largely decided by functions provided by the WordPress core and in this case, Advanced Custom Fields. Isolating persistence into an EmployeePersister class would simply mean that we create an additional layer between the WordPress database functions and the rest of our code. WordPress wraps the MySQL functions into an API and then we come along and wrap that API in another API. Does is make sense to create a separate class for 4-5 lines of code?
Well, it could make sense. If already know that we want to provide a Drupal version of that same plugin. Or perhaps we want to move away from using a custom post type to using our own database tables instead. If any of those two changes are actually realistic, we should go ahead and put the persistence specific code in a separate class.
But if you’re reasonably certain that such changes will not occur, then you can probably safely use the one Employee class for both types functions.
But then again, it could turn out that loading and saving the Employee internal state requires a lot of additional logic that is subject to change at a later time. In that case following the SRP and create a separate EmployeePersister class makes sense.
Applying the SRP requires us to find a balance between strict design and some sort of manageable reality. If we try too hard to look into the future and foresee every potential change, we’re probably going to end up with things we’re never going to need (YAGNI) which is bad in itself.
One way to understand the SRP is to consider the very opposite. A god-object, sometimes also called a god-class. We say that we have a a god object (or function) when a lot or even all of our code ends up in one really big class with lots methods, complex internal state, tons of dependencies and lots of responsibilities. Think of this one class as the god of your system, everything depends on it and it depends of nearly everything else. Even if the term god-object typically means the main class file of a system, god-objects are found in sub systems as well. In WordPress we can see an overall well designed plugin have local god-objects for certain things, I’ve seen a lot of Widgets implemented as de-facto god-objects.
The god object is a well known anti pattern (a common solution seen in system design that is usually ineffective and risky). A god-object often turns in to a maintenance nightmare, are difficult to debug and nearly impossible to test using standard tolls such as PHPUnit. We should avoid them.
A few signs that one of your classes might be trying to do too much:
Your class is very long. If your class grows a lot beyond 1000 effective (not counting comments and white space) lines of code, you can probably split it into smaller classes with more distinct responsibilities
One or many of the methods in your class grows beyond 100 effective lines of code. Large functions can usually be broken up into several smaller functions.
The total number of methods (excluding getters and setters) grows too far beyond 25. This depends a lot on the specific class, but too many functions is an indication that your class is doing too many things.
Your class declares a mix of static functions and instance functions. This is needed in some specific cases like to implement the singleton pattern. But if there’s a mix of static and non-static functions it usually means that the static functions has nothing to do with the object state and therefore could have been refactored into a separate class.
Your class has functions that outputs HTML or CSS code directly (example). Following the SRP, a better option would be to separate HTML snippets and entire pages into their own files.
Your class constructor have side effects on global state (state that is not part of your actual class). Typically via calls to add_action or add_filter (same example). This makes it a lot harder, sometimes impossible, to write unit tests for your class.
Your main class file can’t even be included or required into a stand alone script without first loading WordPress. This is typically seen in cases where a developer mixes a class definition and old school procedural code into the same module. So that even loading that class have the side effect that a piece of procedural PHP code gets executed (same example again)
If your code does more than one of the above things there’s a chance that you will get long term benefits from splitting your class into smaller ones.
A great tool to get you started with analyzing your code is the PHP Mess detector. It’s a static code analyzer that checks your code for a number of metrics including the size of your classes and functions.
Example: The WordPress plugin boilerplate
A very pragmatic thing to do is to look at the specific real life case with a WordPress theme or plugin. A good place to look at is the WordPress plugin boilerplate written by Tom McFarlin’sWPPB foundation plugin (now maintained by Devin Vinson). It’s a foundation that many WordPress plugin are based on and it provides a good starting point of how to apply the SRP in a WordPress environment. From a birds eye perspective, the boilerplate is organized like this (lots of details excluded):
The main plugin file serves to bootstrap the rest of the plugin. It’s the only file that WordPress core really knows anything about and it’s what gets included in at every request to the server. The main job is to load the main class and hook it up to the WordPress init function.
The includes folder is where all common code is placed, including the main plugin file. Note that there are separate PHP modules for plugin activation and deactivation, each with a single responsibility. The boilerplate even uses a separate module to register all WordPress actions and filters needed by the plugin.
The admin folder is for all code that is related to the admin dashboard pages needed by this plugin. The one thing to note here is that the boilerplate encourages us to keep functionality in the main admin class but everything that renders HTML in a separate views folder (it’s actually called “partials” in real life).
The public folderhas the exact same structure as the admin folder, but it’s intended for functionality and views that are used on the front end.
This basic structure of classes and folders provides an idea about how to separate different things into different folders and classes. Naturally, once you decide to base your plugin on this boilerplate, you will have plenty of opportunity to violate the SRP within this structure. Jamming all vital functionality into the main plugin class takes you right back to an evil god-object.
Look at the boilerplate as a starting point, as soon as your plugin gains in complexity, it’s your job to ensure that the code you add doesn’t pack too much into one place. Be generous with creating additional classes and make sure that similar functionality is keps grouped together and well isolated. Consider what types of reasons that could drive change in your project.
(note: There are some aspects of the plugin boilerplate that I think could be done differently to work better with other SOLID principles. Especially regarding dependency injection, but that’s a topic for another post)
Over to you
Do you have a specific question or do you just have something to add? Let me know in the comments below.
There are no shortage of acronyms in the field of computer programming. Some of those acronyms might come and go like a one hit wonder, others are here to stay. Robert “Uncle Bob” Martin first introduced the SOLID principles in the early 2000s and they’ve been around ever since. It’s an evergreen.
First they were just called “the first five principles” and is a collection of ideas brought forward by Robert Martin himself as well as other computer scientists before him. Just a few years later Michael Feathers came along and dubbed them SOLID which makes them a lot more fun and absolutely more memorable.
Uncle Bob argued that by sticking to these 5 “first” principles of software design, a system will be much easier to maintain and extend over time. Code that is written in adherence with the SOLID principles typically also turns out to be very clean and much more testable than code that violates them. If that’s not enough to pique your interest about a soon to be 20 year old set of ideas, I can reveal that the SOLID principles have stood up well against the tests of time. Each of the five principles are still very relevant and can help us write better code.
As with most things in life, there’s a balance between being dogmatic and pragmatic, between being short sighted or planning for the long run. In a series of five posts, I’ll be talking about the five principles and how they can help us write better WordPress themes and plugins.
Knowing about and understanding the SOLID principles isn’t a guarantee against unclean or bad code. Think of the principles as something to lean on whenever you’re trying to work out how to design your code.In my own work, I often find that the cause of a messy code problem is a bad overall design. Solving the design issues typically makes the coding part much easier.
So if you ever find yourself going too slow through a project because it has become too complicated, you could take a step back and consider the SOLID principles. They might be just what you’ve been looking for.
Q: Creating all objects in a DI Container up front seems expensive, what about performance?
Yes and no. Even if most DI containers do support lady loading in various forms, an instance injected into another object still requires to be created first. And sure, there’s a risk that objects get created even if it wasn’t strictly necessary. On the other hand, if you constructors so that object creation is as cheap as possible, this problem might not even be a problem. As a general rule, creating an object should have no for few side effects. In the Hello Testable sample code, an obvious enhancement would be to let the Lyrics object defer loading the text file until it’s strictly needed.
Q: In the original post you kind of describe Interfaces but you never actually use or even mention them. Why?
I agree, the relationship between the main plugin class and the Lyrics class can be made stronger and more formal by defining an Interface and requiring that the object passed into the main plugin class constructor implements that Interface. The only real reason I didn’t do that the original post already tried to stuff too many concepts into a single piece as it was.
Q: If I implement my plugin like you suggest, another developer wont be able to use remove_action to unhook my code. That’s a big problem
Agree, this is an issue. My solution to this is to provide a static method to the needed classes (just the main plugin class in the Hello Testable sample) so that an external piece of code can get a hold of the correct instance for this purpose. I will add a separate post about this when time permits.
I’ve had this post in my head for quite some time now, but I’ve never really found the time to write it. But then a few days ago, Tom McFarlin wrote about how we should avoid calling add_action and add_filter in a class constructor, something I obviously agree with. From some of the comments on Toms post, I realized that some concepts of OOP and writing testable code deserves some additional explanation. I tried to write a comment reply to cover some of the basics, but quickly realized that it’s better to actually get this post out the door.
Not that Tom didn’t do an excellent job with his part, just that I think that we could zoom out a little further so that we more pieces of the puzzle. To get that complete perspective, let’s introduce the star of this show…..
Introducing testable Hello Dolly
With the risk of choosing a too simple example, I’ve created an object oriented version of the classic Hello Dolly plugin, originally written by Matt Mullenweg.
My version is simply called Hello Testable and demonstrates a few of the things I tend to emphasize while writing high quality code for WordPress. The main objective is to show how WordPress plugin code can be made testable and more maintainable by following a few simple principles. Hopefully, I also successfully explain why “testable code” is not just something you fix towards the end of a project, it’s something you should have in the back of your head all along the way.
All the code for this post is available at GitHub. Most interesting parts of the code will be repeated in this post, but for reference and completion you might still want to have a look.
Excuses in advance
Before working with WordPress, I’ve spent a lot of time working with other PHP projects. As a result, I tend to write PRS2 style code rather than follow the WordPress code style guidelines. I’m terribly sorry about any confusion this may cause. Some day I will get in line with the rest of you.
Before going into details and trying to make the case for my approach, let’s look at what happens when the Hello Testable plugin runs.
In the first part, the plugin bootstrap file gets included (1) by WordPress core as you’d normally expect. But instead of directly creating our main plugin class (this is an OOP version, right?) an instance of a Dependency Injection container is created (2). Once we have a container, the bootstrap file asks the container to give it an instance of the helloTestable class (3).
But there is a little caveat. The main plugin class constructor expects that an instance of a Lyrics object is passed in as a parameter. The container object knows this, so it goes about and creates a Lyrics object first and then uses it to create the main plugin class instance (4). This knowledge about how to create other objects is represented in the RuntimeProvider class.
Once the bootstrap function get’s the main plugin class instance back (5), it tells WordPress core that the init function of the class should be hooked up with the WordPress ‘init’ action (6). A little later, when all other plugins had their chance to load, WordPress core will come back and actually call the init function on the main plugin class (7). The init method will in turn hook up two other functions, echoLyric and echoCss to be called by WordPress in response to the ‘admin_notices’ and ‘admin_css’ events, this is not shown in the image above.
And even later when WordPress is ready to render the page, core is going to come back and actually fire the ‘admin_notices’ and ‘admin_css’ events. This is what that parts looks like:
As you can see, at this phase the bootstrap file and the container class has nothing to do with the flow. This is just the normal WordPress flow as you’d expect. A piece of css is echo’ed out and a little bit later, a piece of html follows.
The original Hello Dolly plugin uses the simplest imaginable plugin design. A single PHP file that does everything. My plugin follows a rather different approach:
The point of introducing the dependency injection container is that we get a distinction between creating an object and using an object. For anyone asking why, the easy explanation is that this is what you get if you want your classes to have zero dependencies, for a more in depth answer: read the rest of this post.
In this design, all dependencies are concentrated to the bootstrap module (a simple php file) and the Runtime provider class. The Main plugin class and the Lyrics class doesn’t have any dependencies on any other named class. And by concentrating the amount of dependencies to a single place (ok, two places) we end up with a class design that lends itself well to unit testing. More on that later.
Some formal background
So I’m suggesting an overly complex approach to solving a problem that Matt Mullenweg solved in roughly 80 lines of code years ago. Why? Well, obviously I’m doing this to show you something important and to begin explaining what that is, I first need to mention three (and a half) quite important topics in software design, namely:
Reducing tight coupling and dependencies
When we write code in a module or class that has strong dependencies on other classes and modules, we end up with tightly coupled code, or code with a lot of internal or external dependencies. The way we have written software in the WordPress community has over the years led to a lot of very tightly coupled code.
The problem with tightly coupled code is that we make a simple change in one place, we often get ripple effects that ends up affecting code in lots of different places. It also makes code reuse a lot more difficult. When the code in one class makes explicit assumptions about the mere existence of another class, our first class has a dependency of that other class. As you can imagine, this is quite common in WordPress, we have lots of dependencies everywhere!
As a rule of thumb, anytime you use the new keyword or call a static member of another class, your current class has a dependency on that other class and it’s worth examining if it’s avoidable. The same thing is also true if you ever call a non internal php function in the global namespace, that’s also a kind of dependency. Avoiding global functions is obviously going to be tricky in a WordPress environment and as we shall see later, globals do make our job a bit harder once we get to writing tests. In the WordPress world, we’re going to have to live with global functions for a long time, but there’s no need for us to add more global functions into our own plugins and themes.
Dependency inversion principle and dependency injection
Dependency inversion principle offers a solution to the problem of tight coupling. At the practical level, it simply means that instead of letting code in a class explicitly refer to other classes and create new objects that it needs, we should get those objects passed in to it before they are needed. A class could accept the needed objects via its constructor or via getters and setters, the how is not as important as the why.
As most people figure out, if we pass in all objects to our class via some mechanism, we still need to instantiate those objects somewhere. In a simple application, we could create all needed objects as part of a simple bootstrap function. When the class structure gets a little bit more complex, we could use a dependency injection container as a practical way to manage the object creation in one single place. By adding a dependency injection container to our solution we get an excellent tool for avoiding tightly coupled code.
Separation of concerns
The third principle is about separation of concerns. We should strive for code that keeps each module and class to be as lean as possible. This has many advantages. First, we avoid ending up with a ‘god class’ or ‘god object’, a large do-it-all piece of code that keeps track of everyone and everything. A god class (or worse, function) is a known anti pattern and deals with application control flow, it reads and write files, it encapsulates configuration and usually a 100 or so other things. God classes are often a mess to maintain and debug or even understand just a days after implementation. It’s better to divide the code into smaller, single purpose classes where each class has a distinct responsibility.
The second advantage with separation of concerns is that it promotes reusable code. Chances are that once we’ve put everything that has to do with i.e. reading and writing settings into a separate class, it’s a whole lot easier to reuse that code in other classes.
Avoid side effects
The last topic is picked up from the PHP Framework Interop Group standard PSR1. Section 2.3. It states that loading a module should either declare things (classes, constants, functions etc.) or it should execute logic. It should never do both. I’m sure there’s a non-PHP specific computer science name for this principle, but I’m going to be honest and tell you that my main reason for thinking this is important is because it makes my life as a PHP coder easier.
Hello Testable implementation
Having these concepts in mind, let’s look at the implementation of Hello Testable and how hopefully some of the design decisions I’ve made starts to make sense. First, let’s look at the bootstrap function in hello-testable.php:
The role of the bootstrap function here is to kick of the process of setting up our plugin. It’s called as a side effect when WordPress includes our plugin file.
First we’re trying to exit early from ajax requests since we’re not dealing with ajax.
Next, we’re checking that we are on a new enough version of PHP, this deserves a comment. To make everything work as we need, we’re going to use auto loading and namespaces through the magic of Composer and 5.3.9 is the earliest version Composer will run on. While it’s theoretically possible to get our job done without it and make the code PHP 5.2 compliant, I happen to think that it’s reasonable to skip 5.2 support. Someone else has already built a well supported and fully functioning package manager (Composer) with auto loading and namespace support that the rest of the PHP community adopted years ago. It makes sense to use it even if it’s at the expense of those poor souls who are still maintaining WordPress on PHP 5.2.
I’m sure all 5.2 users are happy that WordPress still runs on their 11 year old web servers that hasn’t been supported for the past 6 years, but I think it would be unreasonable for them to expect that all new code written for WordPress will.
Line 21 is where the fun stuff starts, we’re creating an instance of a Container and on the next row we initialize the container using our own RuntimeProvider class.
Some of you might notice that I’m creating an instance of Pimple (a well known 3rd party dependency injection container) but it appears that Pimple is part of our own, plugin specific, namespace. Isn’t that weird since we’re using Composer and all? Well, yes and yes. I have made a copy of Pimple and made it part of our own code base. And yes, in an ideal world this is exactly the kind of thing that Composer could help us avoid. The problem here is WordPress.
As described in this post, it’s not really safe to include 3rd party libraries via Composer into a plugin or theme for several reasons. In order to safely take full advantage of Composers package management, WordPress would need to have a centralized vendor folder where all 3rd party libraries reside. As things stands right now, another plugin in my WordPress installation could already be using an incompatible version of Pimple and if that’s the case, my plugin would break. So for now, we should be very careful with including 3rd party libraries via Composer into WordPress themes and plugins, especially if we intend to distribute them. Making a local copy of Pimple and renaming it’s namespace is a pragmatic solution to this problem and Pimple has a fairly small implementation so it’s not that expensive anyway.
Next, our bootstrap function asks the dependency injection container for an instance of the main plugin class and then lastly hook the init function up to the WordPress init event. Note that we’re explicit here, we first create the instance of the main plugin class, then we’re explicitly calling add_action. There’s a reason and we’ll get back to it when we look at unit tests for this class.
Also note that this module actually violates the side effects principle, it obviously defines a constant as well as two functions and it certainly executes some logic. My honest opinion is that it’s OK to violate that principle (and a few others) in the bootstrap module, but that’s about the only place it’s OK. I’m sure a lot of pragmatic people will agree, if you don’t agree, please let me know in the comments below.
RuntimeProvider.php – initialize the container
The role of the RuntimeProvider class is simply to initialize the Pimple container:
This is standard Pimple setup where we tell the container how to provide objects of the different classes we’re going to use. When the bootstrap class initializes the Pimple container, the code in the RuntimeProvider::Register is executed. Pimple promotes lazy loading, so it’s not until anyone actually wants a Lyrics object that the closure function will be executed and a Lyrics object is created. In our little sample, we have little use of lazy loading since all objects will be created at plugin load time. But it’s worth mentioning that this approach doesn’t always mean that all objects are always created at plugin load time since it’s a common misconception. It will simply depend a little bit on your code at large.
The Lyrics class constructor takes a file name as parameter and the main plugin class, helloTestable, wants a Lyrics object as parameter to the class constructor. Pimple will resolve the dependency between helloTestable and Lyrics so that when we ask for helloTestable, a Lyrics object is created on the fly.
Lyrics.php – Fetching lyrics
Consistent with the principle of separate concerns, the main plugin class doesn’t concern itself with reading lyrics, we’ve put all the lyrics related code into a separate class. Also note that the Lyrics class doesn’t even know anything about the song Hello Dolly, it just happily accepts the path to an external file to parse.
(note, this has some security implications since anyone with write access to the server could replace the content of the file with something dangerous, it can be mitigated but that’s outside the scope of this post)
If you have seen the source of the original Hello Dolly song, this should look somewhat familiar.
helloTestable.php – The main plugin class
The last class we’re going to look at is the main plugin class. We’ll do this function by function, first, the constructor:
Real life dependency injection!
This is a typical constructor in a class that uses dependency injection, the only real thing that happens is that we store the injected dependency into a private member variable. Apart from that, nothing and that’s exactly the intention. We don’t want the class constructor to fiddle with anything except it’s own internal state, creating an object should have no side effects on state anywhere else in our application.
Next, we know from looking at the bootstrap code earlier that after creation, the bootstrap function will hook up the WordPress init event to the init method of this class, this is where the class gets to do things that affects the state of anything external:
This should be very familiar WordPress code. Note that we hook up the events to instance functions rather than static functions that you also often see in WordPress code.
The two last functions should be fairly straight forward:
Both these functions are almost but not quite completely uninteresting. You want to note that the echoLyric function is where we use the Lyrics object that was passed in via the constructor earlier. It’s actually the only place in the main plugin class where we make any assumptions at all regarding the Lyrics object, the assumption that there is a function named ‘getLyric’.
This is a fine example of separation of concerns, the main class needs to know absolutely nothing about how lyric strings are created. In a later version of this plugin, we might want to change the implementation of Lyrics so that it reads 10 files with 10 songs and displays half of them backwards. Those changes would only affect the Lyrics class, the main plugin class would remain untouched. The other benefit from following the principle of separate concerns is that the Lyrics class is easy reusable. At some point we might want to get a lyrics string as part of an ajax call to WordPress, and if so, the Lyrics class is easy to reuse.
It’s also a fine example of minimizing dependencies. Back in the RuntimeProvider class, we could create any kind of PHP object we like and pass it as a dependency to the main plugin class, as long as that class has an function called getLyric(), our code will work just fine. We could implement a new class called HttpLyrics that fetches the actual strings from a http server somewhere, or a class called DBLyrics that uses a database table to get it’s lyric strings. The main plugin class will never know the difference.
Code complete – let’s test
With that, we’ve finished talking about the implementation and had a look at all the interesting pieces of code from an implementation perspective. We’ve already seen that while real life usage of some of these principles gives some additional overhead, they start to pay off quite quickly in that our code is nicely modularized and easy to extend.
When we now turn to writing unit tests, we’re going to see even more advantages pan out in real life. I fully understand that even if some of the design decisions I’ve made starts to make sense, I think you’ll see that some of them are more or less mandatory as we strive for fully testable PHP code.
First, a word about unit testing.
Unit testing means that we should test our code in the smallest possible executable units. In PHP the smallest executable unit is typically a function so what we want is to test each function individually. The challenge is that most function often calls other functions, sometimes in other classes and sometimes functions in the global scope. It can quickly become quite messy to isolate each function so that test only concerns that specific function.
This is where the idea of avoiding dependencies in classes, having code modules that loads without side effects and writing code according to the principle of separate concerns should start to sound a little bit more appealing.
We know from experience that WordPress uses a lot of functions in the global scope so it doesn’t really matter how good our own OOP design is, if we’re dealing with WordPress we’re going to have to deal with global functions. Also, some of those functions will interact with the database or make assumptions that other parts of WordPress is initialized. It becomes messy real quick.
In unit testing, the solution to this kind of mess is to work with mock objects and functions. If our code calls a global function like add_action, we can mock that function instead of trying to load the relevant parts of WordPress. Mock function and objects can if used correctly, enable us to fully test our WordPress plugin without ever having to load WordPress. Besides that good feeling you get when following some computer science dogmatic principle that also means that your unit tests can be executed super fast. And lets face it, if the unit test suite takes 2 seconds to complete, youre going to run them a whole lot more often than if it takes 10 minutes.
There are lots of mocking libraries for PHP and PHPUnit but the gold standard of mocking WordPress code is a framework from 10up called (surprise!!) WP_Mock. WP_Mock can be a little bit tricky to get started with so I hope that this post also serves to give a few pointers on how that can be done. But this is not a WP_Mock tutorial so let me know in the comments if you think that’s something you’d like to see as a separate post later.
Let’s dive in and look at testing.
First test class – LyricsTest.php
This test class is for testing the Lyrics object. It really only have one interesting method, the constructor will get test coverage as a side effect from running this test:
We’re creating an instance of our Lyrics class. But instead of giving it the standard lyrics for Hello Dolly, we’re passing in a file from the fixtures sub folder. This file just contains 3 rows, all beginning with the word line and a space. This makes it easier for us to write predicable assertions for this function.
Here we also need to use WP_Mock to emulate the WordPress function wptexturize. Remember that our unit tests should run isolated, so including the WordPress implementation of this function is not an option (if we did, we’d be writing an integration test). Our mock implementation of wptexturize just returns the same string but with a space and the word wptexturize added. This makes it easier to verify that our code ran as we expected, a neat little testing trick.
This is what a unit test for WordPress plugin code will often look like.
We create our object as normal, we only need to pass in our known dependencies.
We mock a couple of WordPress functions from the global namespace and then run our function.
Then to round up, we verify that we got the expected result by running a couple of assertions.
Next up – helloTestableTest.php
When testing the main plugin class, we have to use a few slightly different approaches. First of all, the main plugin class init function deals with WordPress internals, it doesn’t really return any data that we can test with assertions. But we can test that the expected add_action functions are called. Here, we talk about setting up expectations for our code and then WP_Mock will verify that our expectations are met:
For this particular test, we don’t even need to bother with passing in a functional Lyrics object since we know that the init function won’t use it and the constructor will only store it, so we can pass in a dummy. Next, we tell WP_Mock that we expect to get two calls to add_action with different parameters. When we run the init method from our test case, WP_Mock will thrown an error if the expectations weren’t met. Since we don’t have any return data from add_action, that’s about the only quality assurance we can do on this code.
Now stop for a minute and ponder the original statement made in Tom McFarlins post about calling add_action in the class constructor. If our main plugin class had violated that principle, we couldn’t have written this test.
In order to set up the expectations for WP_Mock, we’d first need to have an instance of the class. But creating an instance of the class would have already have called the add_action function and we’d miss our opportunity to check for it. So if you’ve read this whole post just to find an additional argument for Tom’s statement, this is it!
Next step is to test the echoLyric function. When doing this, we’re again getting an advantage of the fact that our code so far has very few dependencies. All that function cares about is that it can call a function called getLyric() on a private member variable. We could pass in our already quite easily testable Lyric class and just feed it a predictable text file, but that wouldn’t be testing in isolation so we want to avoid it. Another option would be to use WP_Mock och PHPUnits support for mock objects, they both have good support. But I’m going to show you another testing trick that I use a lot, creating your own mock classes:
First the mock class (located in tests/MockObjects.php):
Then the actual test case code:
Two things to notice. With our mock test class, it’s easy enough for it to just return whatever we initialize it with, it just needs to implement the expected getLyric() function. Creating simple mock objects like this is often very helpful.
Second, the echoLyric function in our main plugin class echoes out directly to standard out so we don’t have any return value to test against. Instead we’re using PHPUnits expectOutputRegex function to ensure that the outputted text contains the string that we initialized the mock object with.
Let’s stop again and think about what this would look like if we had implemented the Lyrics object with static functions and we wanted to test echoLyric(). In that case, the class name ‘Lyrics’ would already be hard coded into the code of helloTestable.php and we’d have a hard dependency to work with. It wouldn’t have been possible to mock the Lyrics object in any sensible way and we would have to accept a test that wasn’t as isolated. We’d be stuck with our test case indirectly using the standard implementation of the Lyrics class and we’d also be stuck with any dependencies that in turn would have. For this simple plugin it wouldn’t be a big deal, but imagine if the Lyrics class fetched lyrics data over http from a very slow or unreliable host. Our test would then depend on that unreliable host.
The last function in the main class is the echoCss function. This function uses the WordPress global function is_rtl() that we need to mock. For good measure, we test both possible return values from this function. This is easy to do in WP_Mock by defining a ‘return_in_order’ element that will give different return values for the first and second time it’s called:
Last but not least – RuntimeProviderTest.php
The runtime provider only have one function and we’re just going to write one test case for it and it’s really straight forward:
Asserting that we get the right kind of object when asking the container is really the only thing that makes sense to test.
With the above tests in place, we should be able to run phpunit from the command line and end up with a coverage report like this:
Some 4500 words after I decided to add a few comments and insights to a post by Tom McFarlin, here we are. The point originally made was that we should avoid calling add_action and add_filter in class constructors which is still very true. If you made it this far into the post, you hopefully also agree that it a good idea.
Hopefully you also agree that it’s a good idea to consider what happens when follow a handful rather simple and obvious rules of how to write code. Rules by the way that have been known in computer science community for decades by now. Follow them and you’ll end up with testable and maintainable code. And as always, once you know the rules and how they help you write better code, you may break them as much as you want because you understand the consequences.
While writing this I think I’ve left out more examples than I left in, there are tons of other points to be made, samples to be shown and arguments to be had. Please let me know what you got out of this. Questions or opinions alike, I’d love to hear from you in the comments section.
I’ve just released version 0.1.2 of wp-checksum a new wp-cli sub command.
Wp-cli has been able to verify checksums of the WordPress core for some time now. This is a powerful command whenever you’re dealing with a site that might be hacked. With Wp-checksum, we bring the verification functionality to standard plugin and themes as well. Finding one or more of files in a WordPress installation that have been altered is a very serious warning signal. Having a tool that checks each individual file automatically is very powerful.
What does it do?
The tool will index every single file inside each theme or plugins folder and calculate a checksum for it. That checksum is then compared to the checksum of the same file of the original plugin code. Wp-checksum also detects new files that have been added to the plugin folder. Any plugin and theme that was originally installed from the WordPress repository can be checked.
The default output format is a standard wp-cli formatted table. But there are options to output as json, yaml or csv as well.
At this point, the wp-checksum command uses a centralized database that keeps track of all versions of all themes and plugins on the repo, accessible via an API. Using a centralized database is not only beneficial for performance reasons, it also means that over time we should be able to include some of the most popular premium plugins in there.
It’s on Github
To install and try wp-checksum on your installation, head on over to github to read more and get the installation instructions.
In the previous tutorial, we covered how to set up a simple WordPress site using WP Bootstrap, essentially preparing the site for git and git based deployments. In this tutorial we’re taking the next step. We’re going to add all the needed files to a Git repository and after that we’re going to deploy the code into a production environment.
Update 2016-01-11: After this post was first published, I’ve published wp-deployhelper, a tool intended to speed up deployments to shared hosts. If you’re interested in fast shared host deployments I strongly suggest you have a look at wp-deployhelper.
We’ll look at how we can deploy changes to the production environment regardless if you have ssh access with composer and wp-cli available, or if you’re working with a standard shared host using ftp access. Full ssh access to production is going to be better 999 out of 1000 times. But many WordPress developers have little or no influence over where their customers sites are hosted and we want to document a solid work flow even for this (very common) scenario.
The deployment technique outlined here is based on the very most basic git usage with a manual pull in the target environment. There are other more sophisticated ways like Capistrano or Rocketeer to get the job done and those will be covered at another time, in this tutorial focus is on the basics.
The steps covered in this tutorial are:
Initiating a local git repository and adding files to a Github repository
Checking out the project files on the production environment and set up the site for the first time
Making changes in the development environment and deploying them to production
Step 1: Initiating a local git repository and adding files
This step assumes that you have already created a repository on Github. We’re using a repository named “tutorial-simplesite1” for this part. Note that some of the commands below contains both the Github username and repository names, make sure you modify these if you copy/paste directly from this tutorial. You also need to have git installed and setup properly, it’s included by default inside the Vagrant environment we’re using. But apart from installing it, you will also need to set up name and email address and perhaps add an ssh key. Please refer to the help pages on Github on how to get started with Git and how to set up keys.
Make sure you the Vagrant machine is running (vagrant up) and that you are in a shell inside the machine (vagrant ssh) in the path where the development environment is ($ cd /vagrrant).
First, we’ll create a local git repository directly in the development environment;
Set up the connection with Github and push, note that this assumes you are using Github with the same repository name as in this tutorial. Replace hostname, username and repository name to suit your conditions.
Step 3: Checking out the files on the production server
Note: In your production environment, I strongly discourage keeping the project files directly in the web root folder. In most hosting scenarios, you can keep the project files in a folder that’s not directly accessible via the web. If you have no choice, you must remove all sensitive information from localsettings.json once WordPress has installed for the first time.
Scenario 1. A server you can access via ssh with wp-cli and composer are installed.
In this scenario, we’re assuming that you are are working in your users home directory and that the web server is configured to use /var/www/tutorial-simplesite1. We’re also assuming that you have created a database and have the user name and password available.
Log in to the server and navigate to the folder where you want to keep your local copy of the code. Note that during checkout, a sub folder will be created, so run this command from one level above. Here we’ll create a sub folder projects under the users home directory:
$ cd /home/user/
$ mkdir projects
$ cd projects
$ git clone firstname.lastname@example.org:yourusername/tutorial-simplesite1.git
Then install WP Bootstrap via composer
$ composer update
…and initialize WP Bootstrap for access via Composer scripts:
$ vendor/bin/wpbootstrap wp-init-composer
Next, generate a localsettings file:
$ composer wp-init
Edit the contents of localsettings.json to suit your server:
Scenario 2. Standard shared hosting with only ftp access
In this scenario, we’re assuming that the production server is perfectly normal shared host. The steps in this section are tested against a simple $3.95/month account on Bluehost but the steps should be easy to reproduce on most shared hosts. To follow these steps you need to have ftp username/password as well as the database credentials, host, database name, username and password.
The next perquisite for this scenario to work is that your shared host allow remote access to the MySQL server. Some hosts have no restrictions for this at all, while Bluehost and many other hosts allow you to open access to the MySQL server for a specific IP address. Bluehost outlines the steps needed here: Remote Database Connection Setup. If you’re on a different host you can probably find help via their support pages.
Using Git to deploy your site to a shared host is based on the following idea:
We will use a local vagrant machine to check out the code, just as the first steps above
When creating the localsettings.json file, we will use the credentials for the production database on the shared host
Then we run the WP Bootstrap scripts to install, setup and import
At last, we will transfer the file tree to the shared host using ftp
If you are using the Vagrant skeleton that was suggested in the previous tutorial, you should already have a staging environment in your local vagrant machine that we will use.
First make sure your vagrant machine is up and running (vagrant up) and that you have ssh’ed into it (vagrant ssh). Then at the command line in the vagrant box,
$ cd /srv/staging
The nginx default setting in the Vagrant box is that the staging WordPress installation should be at /srv/staging/wordpress, so create that folder:
…and initialize WP Bootstrap for access via Composer scripts:
$ vendor/bin/wpbootstrap wp-init-composer
Next, generate a localsettings file:
$ composer wp-init
Edit the contents of localsettings to suit the your domain name database credentials for your shared host. Note that we’re still pointing at a local folder for the installation. That’s because we’re setting everything up there first.
After this, you should be able to see your site via the local URL to the staging server, but it will be slow and look terrible. The reasons for that is that (1) it’s using the database on your shared host which will be a lot slower that a local and (2) all internal links, including those for css and image files are now pointing to the production URL. We will not adress those issues right now, instead we’re going to do the very last step, to transfer the files to the shared host.
The bulk of the work will be done using a tool named sitecopy. It’s been around for a long time and it’s sole purpose is to ensure that a remote version of a site is identical to a local version via FTP. It’s a good fit four our needs. First we need to install sitecopy.
$ sudo apt-get install sitecopy
Next, we’ll create a folder where it keeps its state and the file that controls the behaviour of sitecopy:
Sadly, since we’re dealing with ftp this step is going to take some time, expect 15-30 minutes even for a small WordPress site. But the advantage of using sitecopy is that it’s fairly quick on subsequent updates, at least compared to other ftp tools. If you run the update again, the process should finish in just a few seconds.
On some hosts, Bluehost is one, the database host name in wp-config.php must be ‘localhost’ in order for the site to function properly. But in our WordPress staging installation we have set the host name to ‘box000.bluehost.com’. The best workaround for this is to go in via a standard ftp client and edit the file directly on the server. Then, in order to avoid that this file gets overwritten at future deploys, we exclude it from the scope using a directive called “exclude” in the .sitecopyrc file:
Scenario 2 summary
As we’ve seen, there is a straight forward way to maintain a WordPress site using proper git version control even if we have to deploy the site to a very simple shared host.
But this approach has a few downsides. Performance is one, even a simple WordPress site can take very long for the first deploy to finish. But even subsequent deploys can be challenging since the database might be updated minutes before all new files have been copied to the server.
Another downside is that this is far from as robust as a normal deploy with git and composer directly on the server. For instance, changes to files in core or in plugins that happen on the server are not automatically detected. So sitecopy might think that everything is in sync between staging and production even if there are major differences. Updating plugins and core on the production server is simply not recommended when using this approach. If that happens and the file trees come out of sync, you need to either manually edit the state that sitecopy maintains in ~/.sitecopy/remote (an xml file) or run the command sitecopy remote –fetch to get the current state from the server.
There are a few alternative approaches to keep two file trees in sync via ftp. One is anohter command line tool called lftp that has a pretty powerful feature to mirror two trees, if for some reason sitecopy does not work out for you, lftp might be an alternative.
However, the biggest downside with using ftp for keeping two file trees in sync is that ftp is very slow when it has to deal with large amounts of files and folders. Not because of the connection speed, but because there will be a huge amount of individual ftp requests and each request has a little bit of overhead time.
Some hosts, including Bluehost, offer a limited ssh access to the server, enough to run another file synchronization tool called rsync. Bluehost has an option where you can verify your account with their verification department and after that you can get limited ssh access to your hosting server. I will describe how to set up a rsync based deployment in a later post or tutorial, for now you should at least examine the options on your host. Here’s an article that explains how to get ssh access on Bluehost.
Step 4: Creating changes
Before heading on to the final step in this tutorial, we’re going to make a few changes in development so that we have something to deploy. We’ll make the following changes in the development environment:
Modify code in the child themes functions.php
Modify the title on the welcome page to say “Welcome (git deploy)”
By making these two simple changes, we’ll cover deployment of changed code, normally pretty easy to transfer. But we’re also covering a change that took place in the database, which often is a little bit harder.
First, make sure your vagrant box is still running and use your browser to surf to the development version of your site http://www.casestudy1.local/wp-admin. Log in to the admin area and make the modification to the welcome page. Change the title and feel free to do some changes in the content we created with Page builder. Save the page when your’re done.
Next we’ll make a little change in the child theme. Edit the file [project_folder]/wp-content/themes/vantage-child/functions.php and add the following code under the existing code:
add_filter( 'the_title', 'vantage_child_the_title',10, 2);
function vantage_child_the_title($title, $id = null)
return $title . " [I'm added via code]";
Save the file and go have a look at http://www.casestudy1.local/, you should see that the title has changed, both the changed you did in the page editor as well as the text [I’m added via code]”. Once you have confirmed this, let’s bring up the terminal. Make sure to ssh into the Vagrant machine (vagrant ssh) and go to the correct folder:
$ cd /vagrant
Then we’re going to create a new export so that our database changes are stored in files in the bootstrap folder:
$ composer wp-export
Next, we’ll use git to find out what’s changed (output shortened):
$ git status
Changes not staged for commit:
WP Bootstrap regenerates all files in the bootstrap folder at wp-export, and if the internal ID’s changed during the last import process, chances are that there are small modifications in many files. We see our modified functions.php as well as the welcome page in the list of modified files, so it seems reasonable. We’ll commit these files and push them to the remote repository.
$ git add bootstrap/ wp-content/
$ git commit -m "A few changes"
$ git push
And that’s all for this part, all our changes are now stored safely in Git.
Step 5: Deploying the changes to production
So, in the last step in this tutorial we’re going to deploy these changes into production.
Scenario 1. A server you can access via ssh with wp-cli and composer are installed.
Log in to the server with ssh and navigate to the folder where you want to keep your local copy of the code (the folder where localsettings.json is located). Then do a git pull go get all the changes:
$ git pull
Then, apply any changes in themes or plugins (none in our case) and finally import the modified content
$ composer wp-setup
$ composer wp-import
And that’s actually it. You might want to create a small bash script to run both commands at once, or you might prefer to run them separately as we did above. In this case, we could have just run the wp-import command since we didn’t add any new plugins, but I’ve taken it as a habit to always run them both.
Scenario 2. Standard shared hosting with only ftp access
In this scenario, we’ll do pretty much the same things as above, but we’re going to run it from within our staging environment. Make sure you’re inside your vagrant box and navigate to staging:
$ cd /srv/staging/tutorial-simplesite1
Get the latest version of the code:
$ git pull
And then run the commands to apply changes;
$ composer wp-setup
$ composer wp-import
Now, all the database changes are in place on the production server, we need to push over the modified files as well. First, let’s look at what sitecopy want to transfer:
Besides the functions.php file we know we changed, we’ll also see a bunch of other files that sitecopy think have changed. This is because how the import process works where several files get touched even if they didn’t in fact change. It’s a fairly small extra overhead, so we’ll get going with the final step:
$ sitecopy remote --update
Some more comments on the ftp/sitecopy approach
When writing this tutorial, the update of the above files took a total of 10 seconds. Most of that time was spent on transferering files that hadn’t actually changed. This means that the time between the database has been updated and all the files are in place was 10 seconds. During this time, there’s a fair chance that your site is in an “undefined” state, so we want to do what we can to fix this. Sitecopy offers a way to use checksums rather than the file modification date as detection method. That creates a little bit of overhead before the transfers can start, but it’s often worth it. If you have a lot of media files that is managed using WP Bootstrap, i suggest you add “state checksum” to the .sitecopyrc file:
Combining Git with a “content aware” tool like WP Bootstrap is a fairly powerful combination. By defining precisely what parts of WordPress we need to manage, we can leave all the other stuff untouched. Updating the menu structure never conflicts with existing posts, comments or other content on the production site. So developers can take care of code and certain parts of the site, while writers and editors can manage the content that is just pure content.
Ideas? Questions? Feeling angry or happy? Please share your thoughts in the comment section below.
The most of Christmas celebrations is behind us and in the wake of it all, some time was available to get WP Bootstrap 0.3.0 out the door.
What’s new in 0.3.0 ?
The single most important feature of 0.3.0 is that it introduces the concept of manifest files. So far, it’s really only used for taxonomies, but the general idea will be used for all content types. A manifest file is created when content is exported from a WordPress installation and contains some of the configuration that was used to create the export. During import, data from the manifest file is used to tune the import better.
0.3.0 also introduces the concept of “postid” taxonomies. Some plugins and themes uses taxonomies to tie different post types together using carefully named terms. One of the most popular sliders uses a custom post type “ml-slider” to represent a slider, so that each slider is a post of the “ml-slider” custom post type. Then it creates a term in a custom taxonomy, also named “ml-slider” with the same name/slug as the slider post ID and “tags” attachments (aka images) to that slider using that taxonomy term. In order to successfully export and import this, WP Bootstrap now handles “postid” taxonomies in a way so that even if the slider post has a different ID on the target system. the taxonomy term is renamed accordingly.
Refactoring and testing
Code quality is one of the most important aspects of WP Bootstrap development, so a lot of time was spent on refactoring code and making sure code coverage remains high. All testing activity is done in a separate github repo just for testing. If you want to contribute to WP Bootstrap, this is where I recommend you start looking. The overall test coverage is currently at 86%. I believe that around 90% is a reasonable target to aim for until we get closer to a 1.0 version of the tool. Any contributions to WP Bootstrap are more than welcome, you can just send a pull request or better, shoot me an email first at: email@example.com
Case studies and development process
In the next few days, a case study on how a simple one page WordPress site is managed using WP Bootstrap will be released. While creating that case study some additional bugs were caught and fixed which was good. I also realized the need to implement manifest in order to get the “postid” taxonomy handling in to place. Overall, I think that since WP Bootstrap is now somewhat competent in itself, using real world examples with popular plugins and themes might be the best way to uncover issues and challenges with the tool. The case study will be released on the blog within the next few days, so stay tuned.
New version of the eBook WordPress DevOps
While WP Bootstrap is going to consume a lot of time in early 2016 there’s another project that can finally get started. I’ve promised myself that once WP Bootstrap had a certain level of features, it’s time to update the WordPress DevOps eBook. The current version of the book, let’s call it 1.0, doesn’t even mention WP Bootstrap but instead talk about the concept of using Grunt and a set of loosely defined PHP scripts to do the same work. With the 0.3.0 release of WP Bootstrap it can not only do everything those Grunt scripts could but it can do it better, so the work on next version of the book has officially started.
If you’ve already purchased the book on Leanpub, the next version is free and you will get notified when it’s ready for download.
Stay in the loop
A good idea if you want to stay in the loop is to subscribe to the newsletter, I promise you’ll be the first to know. If you sign up now, you’ll receive a PDF guide with some tips and techniques I use to identify options that needs to be managed using WP Bootstrap and WP-CFM. It’s an 8 page guide that describes how to use wp-cli and some other tools to understand what options that are the most important on your site.
Work with WP-Bootstrap is coming along quite fine. Since the last update, the version number have bumped from 0.2.2 to 0.2.8.
Monolog have been added for proper logging. Along with this, three new optional properties have been added to localsettings.json.
logpath: The path to the logfile. The file will be created if it doesn’t exist.
loglevel: Loglevel for the logfile. Uses one of the constants from the Monlog package; DEBUG, INFO, WARNING etc. See https://github.com/Seldaek/monolog/blob/master/doc/01-usage.md for more information. The default log level is WARNING, so if you specify a log path but no level, warnings and errors will be logged.
consoleloglevel: Log level for logging on the console (standard out), uses the same Monolog constants as loglevel. There’s no default for console log level, so if you don’t specify it, nothing will be logged to the console.
Also in recent releases, media handling has improved. First of all, media are included in exports if they are attached to a post. The new thing is that a featured image (that technically does not have to be attached) will also be included (and restored during import). Lastly, media that is referenced in the post text or in a widget or in a meta property of the post will also be included in the export process. When importing, these files are added to the media library.
Sidebars and widgets are now managed in the export and import process. This means.
Last but not least. Taxonomy terms handling is much improved. Taxonomy terms no longer needs to be explictly mentioned in the export settings to get included, all that is needed is that a post is connected to a term or that a menu item refers to it. During import, taxonomy terms are added or updated and posts are tagged accordingly.
With all the above improvements, WP Bootstrap have now somewhat matured into a quite competent import/export tool for content aside from just being able to “bootstrap” an installation with plugins, themes. I’ve already been using this to do a few site migrations, like when moving content from my personal blog (http://erik.torgesta.com) to this one.
Curious? Take Wp-bootstrap for a spin, read installation instructions and most of what you need to get started over at the github page.
Questions? Use the comment field below and let me know what you think.
Next? I’ve got a post lined up that explains how to use Wp-bootstrap for moving content between installations. Stay tuned.
I first wrote about Wp-bootstrap in a post a few weeks ago and now it’s time for an update.
New version 0.2.2
Version 0.2.2 that was released today is actually quite a release. In this version, Wp-bootstrap is now feature complete to the extent that everything I described in my book, WordPress DevOps is now possible to do using Wp-bootstrap. This means that a bunch of Grunt scripts that quite honestly grew to be fairly complex can be replaced with a well formed, easy to read json file instead. I can’t tell you how nice that feels.
I’ve got a separate repository on Github with the test cases for Wp-bootstrap. For the 0.2.2 release I spent a lot of time making sure to get code coverage up to an acceptable level. The overall coverage is now at 83%, a number I’m quite happy with at the moment. The missing 17% are in a part of the package that I’m considering scrapping and it’s not presented in the documentation, so no one should stumble on the untested code by mistake.
The big thing in this release is reference management. When you import options into WordPress using Wp-bootstrap, you might sometimes include a value that is actually a reference to a post ID. The most obvious example is the WordPress option “page_on_front” that stores the page ID for the page that works as the front page of your site. If you are using Wp-bootstrap to import the front page itself, chances are that the ID of that front page will be different between your development and production installations. So if you import the “page_on_front” setting, the integer value in the database will almost certainly be wrong.
Wp-bootstrap can overcome this problem by managing these references for you. Just tell Wp-bootstrap which settings that contains references to a page/post/term. If that item was included in the imported data, Wp-bootstrap will update the database accordingly. This is a very powerful feature and it works across both posts (pages, posts, attachments custom post types) and taxonomy terms (categories, tags etc).
Intended use case
There is an intended use case or workflow that I had in mind developing this package. A quick overview:
On the development server (hint: use Vagrant):
Start a new project by requiring wp-bootstrap in composer.json
Run vendor/bin/wpboostrap wp-init-composer to get easier access to the wp-bootstrap commands
Create a localsettings.json and appsettings.json
Make sure you exclude localsettings.json from source code control
Initiate the development installation with commands composer wp-install and composer wp-setup
As settings are updated, use the WP-CFM interface in WordPress Admin to include the relevant settings into the application configuration
As plugins and themes are needed, add them to appsettings.json and rerun the wp-setup command to get them installed into your local environment
As posts and menus are added, include them in appsettings.json.
When it’s time to deploy to a staging or production environment, run composer wp-exportcommand to get all content serialized to disk. Add them to your Git repo
On the staging or production server:
Create the local database
Check out the project from Git
Create up your localsettings.json file with the relevant passwords and paths.
Run composer update
Run vendor/bin/wpboostrap wp-init-composer to get easier access to the wp-bootstrap commands
Run composer wp-install, composer wp-setup and composer wp-import
Once the target environment has been setup, new changes from the development environment can be pushed by checking out the new changes using Git and rerunning wp-setup and wp-import.
Take it for a spin
Now it’s over to you. If you’re interested in a more structured workflow around WordPress, give Wp-bootstrap a try and let me know what you think in the comments section. Or better, get in touch to let me know how you can contribute to Wp-bootstrap. I’m eager to hear from you.
I’ve created a PHP Composer package to provide an easier way to automate WordPress installations using wp-cli. If you are unfamiliar with wp-cli and composer. I suggest you read up on composer here, wp-cli here and the rationale of automation in my book or in my blog series on the subject.
Another great resources for learning more about using WordPress, git and Composer together is to check out the roots.io post on the subject as well as their Bedrock project.
What is wp-bootstrap
Wp-bootstrap is a composer package that adds a bunch of commands to your environment that helps you set up WordPress and themes, plugins and settings in a consistent manner using configuration files rather than scripts or worse, point and click installations. Wp-bootstrap depends on two files that it expects to find in your project root folder:
appsettings.json that contains settings, themes and plugins that your WordPress site needs to use. It also has a way to manage some of the content of your application. This file is meant to be a part of your application and managed in a source code control system.
localsettings.json that contains settings that are specific to each environment. This includes database name, password, WordPress installation path and more. This file is meant to be unique to each environment that your site runs in (development, staging, production etc) and is not supposed to be managed by source code control.
By combining these two files wp-bootstrap is able to setup a WordPress installation from scratch, let’s see how.
By running the command “vendor/bin/wpbootstrap wp-init-composer” to add the wp-bootstrap commands to composer so that you can call wp-bootstrap easier, this step is not strictly needed.
In addition to installing wp-bootstrap, you also need to have a localsettings to tell wp-bootstrap where to find your database, some of the credentials and where to install WordPress (where the web server expects to serve the files from). Note that your’re not really supposed to install WordPress in the same folder as your configuration files. Here’s a sample localsettings.json file:
I think it’s fairly self explanatory, but here it goes:
environment is typically one of the values “development”, “staging” or “production”. A description of the environment that this installation is
url The url for this installation
dbhost, dbname, dbuser and dbpass are the database credentials. Wp-bootstrap assumes that a database already exists and is accessible using those credentials
wpuser, wppass are the credentials for the default WordPress admin user.
wppath is the path where WordPress will be installed.
The last thing you need to add is an application settings file. The very minimum file you need to provide is:
"title": "TestingComposer approach";
Title is the only mandatory field in this file, but it’s far from the only one.
This section consists of two sub arrays “standard” and “local”. Each array contains plugin names that should be installed and activated on the target WordPress site.
standard Fetches plugins from the official WordPress repository. If a specific version is needed, specify the version using a colon and the version identifier i.e if-menu:0.2.1
local A list of plugins in your local project folder. Plugins are expected to be located in folder projectroot/wp-content/plugins/. Local plugins are symlinked into place in the wp-content folder of the WordPress installation specified by wppath in localsettings.json
Similar to the plugins section but for themes.
standard Fetches themes from the official WordPress repository. If a specific version is needed, specify the version using a colon and the version identifier i.e footheme:1.1
local A list of themes in your local project folder. The themes are expected to be located in folder projectroot/wp-content/themes/. Local themes are symlinked into place in the wp-content folder of the WordPress installation specified by wppath in localsettings.json
active A string specifying what theme to activate.
A list of settings that will be applied to the WordPress installation using the wp-cli command “option update %s”. Currently only supports simple scalar values (strings and integers)
The easiest way to use wp-bootstrap is to simply call the binary file that is added to your vendor/bin subfolder. Using the sample files above, you could do this:
After running this command, you should have a fully working WordPress installation, accessible via the url specified in your localsettings.json file. The title of the site should match whatever you specified as the title attribute in the appsettings.json file.
So far we’ve managed to reproduce what wp-cli can do in three separate commands, good but perhaps not that great. The real power of wp-bootstrap lies in extending appsettings.json with some more settings. Here’s a slightly more advanced example:
"title": "TestingComposer approach",
"blogname": "New title 2",
"blogdescription": "The next tagline"
Using this file, we can customize the WordPress installation with a new command:
In the Plugins section, we specify a number of standard plugins that will be fetched, installed and activated from the WordPress plugin repository. The if-menu plugins will be installed with version 0.21, but the rest of that list will just be whatever version that is the latest in the repository
We also install and activate a local plugin that will be symlinked from [project root]/wp-content/plugins into the WordPress installation. This is so that we can include our own plugins developed specifically for this project.
The themes section works very similar, the theme agama is added to the installation from the WordPress theme repository and it’s also set as the active theme.
And finally, the settings “blogname” and “blogdescription” are overwritten with the values specified. These names corresponds to what the settings are called in the wp_options database table.
There are more settings…
If you’re curious enough to try this, I suggest you head on over to the github page for this project. It got some additional settings that you should read up on, especially if you’re keen to manage pages, menus and images in a similar fashion.
I’m also very curious to hear what you think about this, don’t hesitate to let me know in the comments. You can also reach out to me on Twitter with comments or questions.
WordPress DevOps – The book
I’ve written an ebook on this subject. Released in September this year on Leanpub.com. Expect a 100+ tightly written pages where we walk through the creation of the skeleton of a WordPress based Saas application, connected to Stripe and Paypal with a working deployment process that takes content into account. Just add your billion dollar idea. Jump on over to Leanpub to get your copy.
WordPress DevOps – Strategies for developing and deploying with WordPress