It’s no secret that the WordPress codebase is a mess. Personally, every time I go through it, all I want is to curl up and cry. On the other hand, WordPress is way ahead of its competition. An easy-to-use and powerful CMS is an enormous undertaking, and WordPress remains popular because it delivers this.
So why would we care about the quality of code in WordPress core? It works, right?
Yes, it works, and the 15-year-old codebase is unlikely to be completely refactored by its volunteer maintainers. Unfortunately, this means it also functions as an example of coding “the WordPress way,” excusing numerous developers for not following best practices and modern development techniques. So many WordPress plugins and themes have infamously bad code, and blindly following legacy practices only continues the trend.
But who cares about bad code that still does its job? Well, nothing is free, and someone pays for a badly done job. With the WordPress codebase itself, its maintainers pay with their time, thankfully. But with your own code, it’s your client who pays.
For any even moderately complex system, the cost of initial development is insignificant compared to the cost of maintaining it, and maintenance also means adding new functionality. Hiring a developer to fix poorly designed and implemented software is going to cost several times more than developing it properly from the start.
Cheap solutions are always the most expensive ones in the long run. Or they get abandoned after running out of budget. We actually save clients’ money when we follow proven software design principles and practices. These methods are not some hyped-up fad, nor change for change’s sake. The wisdom here is born from collective developer experience, and following it really does pay off.
Obviously, this doesn’t apply to truly simple tasks like adding a few lines of CSS or a couple of custom posts and rewrites. But slapping together a few plugins (or more commonly several dozens of plugins) or churning out a Visual Composer-powered site isn’t software engineering, anyway.
That’s not a bad thing, per se—the fact that some solutions are this simple is why WordPress is so popular. But in this series I’ll be talking about real WordPress development: writing significant PHP, HTML, CSS, and JavaScript code. I’ll start with the general workflow and then focus on WordPress front-end development in this article.
In general, quality code is:
The main results—lower cost of development and ownership—have many spinoff benefits that I won’t get into here.
Instead, I’ll focus on which development techniques and best practices can help you to produce quality code. Let’s start with version control.
This means using Git. Sadly, “cowboy coding” on production over FTP is pretty much still a thing. Just recently I worked for a UK-based agency and they had files with names like these all over their codebase:
functions copy.php
functions copy 2.php
functions test.php
functions2.php
functions test2.php
The very first thing you should do when taking on a WordPress site is to put it under version control. Tanking Servers is a fun retrospective of WordPress development mistakes. It would have been very easy to amend those—and similar mishaps that have probably happened to everyone—using Git.
Made a mistake in your code and the whole site went down? git reset
gets everything back the way it was. New version update broke everything? git reset
works as a time machine. Some malicious code appeared from nowhere? git status
shows any new files, deleted files, or changes to any tracked files. Then you just git checkout
, restoring the originals.
.GIT
FOLDEROK, it’s clearly important to use Git. But when you do, it’s just as important to avoid exposing your Git repository to being hacked. The problem comes when you have .git
folders exposed and store your credentials in them.
A standard WordPress installation fully lives in a public web folder, and the .git
folder is very likely to be there as well. Obviously, no login credentials should be stored in the Git repository, but it so happens that most repositories do contain some sensitive information that shouldn’t be leaked outside.
So public access to the .git
folder should be blocked. If you are using Apache, adding the snippet below at the top of the .htaccess
file will block access to the .git
folder and to the log files as well. Log files often contain sensitive information, so it’s wise to make them unavailable as well. For different web server setups, please ask your DevOps expert for help.
RedirectMatch 404 /\.git
RedirectMatch 404 ^.*\.log
Do not do development on live sites—this is a recipe for downtime and unhappy clients. OK, but how should you set it up?
Ideally, there should be three development environments, with code always going in one direction: local → staging → production. This is a proven method for avoiding collisions. All core, plugin, and theme updates are first done locally, then tested on staging, and finally deployed to production.
For example, the server-specific configuration could be stored in a separate file. You can create a wp-config-local.php
for each local and staging environment. (Don’t forget to add it to your .gitignore
file!) Then add the following snippet to wp-config.php
:
if (file_exists(dirname(__FILE__) . '/wp-config-local.php')) :
// use local settings
require_once(dirname(__FILE__) . '/wp-config-local.php');
else :
// production settings
endif;
Often the best way of setting up different environments is using environment variables. If you’re not familiar with this concept, I would advise using a complete modern solution like Roots.
The WordPress command-line interface (WP-CLI) is an extremely useful tool for administering WordPress installations. Having access to WP-CLI means having the ability to run virtually any WordPress API function. For example, you can add, remove, and edit users and their passwords with WP-CLI. Useful if you’ve just inherited a site and the owner has locked themselves out.
Another example is that initial deployment is a breeze with WP-CLI. These can be accomplished with few commands:
Moreover, these actions can be scripted and automated.
Speaking of automation, it’s worth learning some deployment technologies and processes like:
Granted, going from not using version control to dealing with Docker is a huge leap to make and will likely be overwhelming for a typical one-person WordPress project. Some options may not even be possible depending on your hosting provider. But advanced deployment is a must-have for teams and for larger projects.
For projects of any size, though, linting is a boon to most developers. Linting means automatically checking your code for errors. A fully-featured IDE such as PHPStorm already does that out of the box; however, simpler editors such as VSCode or Sublime Text need a dedicated program called a linter. One way of setting this up is configuring your editor to run a linter whenever you save a file.
PHP_CodeSniffer is the de-facto linter for PHP. In addition to checking for syntax errors, it can also check if your code follows style guidelines such as PSR-2. This greatly simplifies following coding standards.
For JavaScript, ESLint is a popular linter. It has an extensive ruleset and supports custom configs for all flavors and frameworks of JavaScript out there.
A powerful use case here is incorporating linting into a CI/CD build pipeline so all code is automatically validated before being deployed.
With a proper workflow now set up for your overall WordPress project, let’s dive into best practices for the front end.
The front-end development world is ever-changing and always in motion. Once we thought that Sass was the best tool for writing CSS—and for pre-Gutenberg WordPress development, it still is—but then everyone began talking about CSS-in-JS and styled components.
Even WordPress couldn’t resist and picked up a few of those new technologies. Gutenberg, the new block editor, is built on React and a REST API.
You should definitely get up to speed with these core front-end technologies:
ES6 and Sass are modern-day JavaScript and CSS, respectively, and Webpack is a tool that allows using all these modern features without worrying about backward compatibility. Webpack can be called a front-end app compiler that generates files for usage in a browser.
The WordPress core and almost all WordPress plugins depend on jQuery, so you can’t just stop using it. Actually, it doesn’t make sense to stop using it for simple tasks such as hiding a couple of
Complex apps are where jQuery struggles: Hard-to-follow logic, callback hell, global variables, and no HTML templating. This clearly calls for a different way of organizing the front-end app.
Modern front-end libraries such as React use object-oriented programming (OOP) principles and organize front-end app architecture into modular, reusable components. A component contains all the code, markup, and “component state” (variables) for a particular element. An element could be almost anything: A button, input field, user form, or a widget that displays recent posts from the WordPress REST API back end. Components can contain other components, forming a hierarchical relationship.
With the complexity of web pages nowadays, organizing an app into components is a proven way of building maintainable, fast web apps of any complexity. Components are highly reusable, isolated, and thus easily testable “bricks,” so it really pays to learn this concept.
There are two component-based libraries that are trending at the moment: Vue.js and React. React would be an obvious choice because it’s already used by Gutenberg. However, for someone new to modern JavaScript, Vue.js could be better to start with.
React throws you into the deep end by using ES6 features, classes, proprietary JSX syntax, and Webpack build pipeline straight away. The learning curve is quite steep.
Vue.js, on the other hand, is much more beginner-friendly, and can be used by just dropping in a tag. Vue.js uses plain JavaScript (ES5), HTML, and CSS. The introduction to new concepts is much more gradual.
After working through a few Vue.js projects, you’ll be better prepared to dive deep into React. Not that it’s always needed, but Gutenberg development, for example, does require it.
WordPress’ REST API is just a standardized interface for remotely requesting and modifying data from WordPress. It’s more a software architecture thing than a completely different way of coding. The same old jQuery AJAX snippets could be used with slightly different parameters.
The most important benefit? Since the WordPress REST API standardizes communication between the back end and front end, it’s a major step towards modularity, reusability, and readability in your code. Those terrible templates with HTML and PHP mixed together and some SQL thrown into the mix have to go. Once templates are just HTML with placeholders for data passed as parameters, there is no major difference between passing that data in PHP or via a REST API to a front-end app.
You may also want to look into WPGraphQL. It may or may not eventually replace the WordPress REST API, but it’s gaining traction fast.