How to write better WordPress code [5 principles]
As a WordPress developer, you probably know how important it is to write good code that is easy to maintain, debug and scale. Every good developer knows how important it is to constantly learn and improve your skills, even if you’re already a seasoned vet.
In this article I’d like to share with you 5 principles that I’ve used when I was developing my last plugin. It doesn’t matter if you’re relatively new to WordPress and have only been working with it for a few months or if you’re an experienced developer. I’m confident that after reading this article you will be able to learn how to write better code, structure your plugins in a way that is easier to maintain and avoid some of the common problems that developers make.
Why is it important to write good code?
Why should any developer care about their code? Why is it important to use the best coding standards when programming?
Those are good questions. One can say that they’re getting paid to get the job done. Ultimately, what matters the most is the business outcome that you have helped your client achieve. Isn’t that right?
That’s only partially true. There are really 2 main reasons why you as a developer should care about your code quality.
- You will have to work with it. This is especially true with bigger projects.
Whenever it comes to projects that require a lot of custom coding, you will have to build a strong foundation first.
When writing a complex plugin you will need to write code that is clean and reusable.
You’re essentially building your own mini framework.
There can be many examples of this: a class that is responsible for rendering views and passing variables to them, a custom router that handles requests, or a custom authentication system.
Things like that usually build the core of your plugin.
They make your mini-framework more extensible and easy to work with.
- You should care about other developers. There is a good chance that you have worked with code that is so bad that you wish you had rewritten it from scratch, right?
That’s the same feeling that someone else might have after reading your code.
At the end of the day, we’re all one community and we should care about our colleagues.
Besides that, you never know who will be working with your code.
A friend of mine was hired after another developer has seen the code he’s written.
- Performance. Writing good quality code has a lot to do with how its’ performance. It should not only look good but also help reduce the load on the server and not make the website slow.
Having said that, let me share with you a little story about me building a WordPress plugin using some of the best coding practices.
5 principles to make your code better that I’ve used building my last plugin
Lately, I’ve been working with membership and subscription websites a lot. I’ve discovered while doing this work that not all of the plugins allow you to protect files from being accessed by people that know the URL of the file – for example, because it has been shared with them by a subscriber. A very popular plugin that didn’t have such functionality out of the box was Restrict Content Pro (RCP). I decided to create an addon/plugin to RCP that would allow admin to give or restrict access to files based on a membership that a person has bought.
Let me share with you some of the main principles that I used when I was building the plugin, to ensure that the code was clean, readable, and easy to extend.
1. Use Object Oriented Programming
WordPress was first created in 2003. Back in the days, php 4 was the latest version and it didn’t have a good implementation of Object Oriented Programming (OOP) built in. It wasn’t until php 5 was released that OOP became a new standard.
Since that time, WordPress has continually been updating their core code to implement the new standards. However, even in 2020, it still has a way to go to become a CMS with an object-oriented code base.
Functional programming can sometimes be handy and I still use it myself. However, it’s important not to overuse it. The one rule that I personally try to follow:
Whenever there is a set of similar functionality, it’s worth considering creating a class for it.
I tend to view functions more like helpers that can help with redundant tasks like string or array manipulations. When working with things that are more complex in their nature like mechanisms related to the application or business itself, I tend to create classes and objects for.
A good example of this might be a routing or an authentication mechanism. I’ve used this principle in my plugin. There is a piece of functionality that is responsible for checking which file is being requested by a user, verifying if a user has access to the file.
If he has, the plugin will allow them to view the file, but if they don’t – it will restrict access.
The class is called Guard.php and you can see it below:
The class encapsulates one piece of functionality.
One could argue that it does a bit too much and doesn’t follow the SRP principle. However, the point here is that classes tend to work better and be a cleaner and more readable solution. Imagine how difficult it would be if instead of one class I had to use 5 or 10 functions and had to “glue” them together to make that piece of functionality work.
If you’ve been a web developer for a while, you’re probably familiar with the concept of Model-View-Controller (MVC). The main reason why this pattern came into existence was the need to separate different aspects of the application(views, business logic) and provide loose coupling between the two. After years of working with this pattern, I think it’s safe to say that this was a very good idea.
2. Separate logic layer from the view layer
While WordPress doesn’t use the MVC principle, I think we can implement the concept behind it to make our code better. This is another principle that I’ve successfully used when building my plugin.
First of all, I’ve created a View class that is responsible for finding the view (locateFile() function) and passing variables to it. The view can be located in my plugin folder, an active theme or a parent theme that the website is using (render() function).
Then, whenever I need to render a view, I just pass the name of the view and add parameters that will be visible in the view itself.
Here is an example:
If I was not using the concept of separating logic from the view, I’d probably have to do all the operations (that you can see in the renderOptionsPage() function) in the view file itself. This would’ve been a disaster to deal with if I were to develop the plugin further.
3. Autoload your classes
If you don’t like using “include” or “require” directives all the time and feel that they don’t make your code better – then you will love the concept of autoloading.
This has been a problem in the PHP world for a long time until Composer has arrived and standardized everything. Unfortunately, Composer is not used in the world of WordPress very often. Many developers don’t even use autoloading at all.
It can be fine for smaller projects, but once your code starts to scale – importing the same file in multiple locations can become tedious and difficult to maintain. Not only that, but it can also increase a possibility of making a breaking change if you were refactoring your code and moving files from one folder to another.
If you’re like me, you probably like to automate repetitive tasks.
That’s why I decided to find on the internet an autoloader class that uses PSR-4 standard and ‘borrow’ it for my own project.
Here is how I’ve used it. First of all, I have a config/autoload.php file that essentially “tells” my autoloader what namespace should I use for the given directory:
And then I have a bootstrap.php file that is included in my main plugin file – rcp-file-protector.php. In the bootstrap.php file, I simply require the Psr4Autoloader.php and the config/autoload.php file and set the configuration.
With that done, I don’t need to manually include my PHP classes in other locations as the autoloader does that job for me.
4. DI container is your friend
Have you ever had a situation when you have a class that accepts 2 or more objects as parameters in its constructor?
Here is an example of one that is used in Symfony Framework:
And this class is being used in 10 different places.
Now imagine that one day you need to add a new parameter to the constructor. In order for your code to keep working, you have to modify 10 other files where your object is being constructed. But what if you have multiple objects that you may need to modify?
Managing all the dependencies can quickly become a complete disaster and can easily introduce bugs to your application. One way you can resolve this issue is to create an object in 1 place and then make it visible everywhere by using a global directive in PHP.
However, I think it’s a bad practice and I don’t like using that approach unless it’s absolutely necessary. We can do a better job with a DI container. So what is a DI container?
The way I think if it is like a box that stores the objects and it knows all of their dependencies. Whenever I need an object, I can simply ‘ask’ the DI container to give me one. It will automatically create it with all the necessary dependencies and give it to me.
You may find it similar to the Factory pattern, but there is a big difference. The former is also responsible for creating objects, however, it is responsible for creating other objects that the object it is creating might depend on.
Let me show you how I’ve used it in my plugin. The following is the implementation of DI container that my plugin has:
I’ve registered a few classes like View, Htaccess, Settings, and others in my container.
The example of the View class is probably the best illustration here. Every time I need a View object, my container is going to run the function that will return me a new View instance with all the parameters it requires.
If you take a look at my Settings class (that is also registered in the DI container), it has a dependency on the View object. Since they are both registered in my DI container, whenever I ask the container to create the Settings object – it’s going to create it with all the necessary dependencies.
Here is a good tutorial that goes a little more in-depth on DI containers in PHP if you’d like to learn more about this concept.
5. Be mindful of other developers
The last principle on my list is to be mindful of other developers.
It’s very likely that either you or somebody else is going to be working with your code so it’s important to make it readable, easy to use and extend.
Here are a few suggestions that you can implement:
- Write comments. Both DocBlock and regular comments in your code can be very helpful. Some developers like me love to dig into the core code to figure out how things work. If there are some parts of your code that aren’t easy to understand – write a short comment explaining how it works.
This can not only help other developers but you as well when you come back to that code in the future.
- Use protected methods instead of private. When I have a method in my class that I don’t want to make public, I almost always use a protected modifier instead of private.
Because then anybody who wants to make changes to my code without modifying the source files can simply extend my class and override the function.
This is a concept that is used in the Laravel community. Just make sure to be mindful when you make a property or a method protected and not overdo it.
So I urge you to try it and see how it works for you.
- Take advantage of WordPress’s actions and filter mechanisms. If you’re a WordPress developer, you probably know that WP allows you to use actions and filters to allow others to introduce changes and extend your code.
Using them is probably the best way that allows people to customize your plugin or theme without altering the source code which is obviously a very bad practice.
- Allow themes to override your plugin’s view files. Some of the most popular plugins like WooCommerce allow you to override some of the view files that they’re using in your theme.
However, this mechanism doesn’t come with WordPress by default. If your plugin isn’t built properly, people won’t be able to override view files in their theme folder.
That’s why if you’re writing a custom plugin, make sure that you implement this to make the lives of your colleagues easier.
In this article, I’ve shared some ideas that have worked well for me when I was building my first plugin for WordPress Plugin Repository. Some of them are concepts that are not just applicable to WordPress, but to web development in general. These are ideas that have stood the test of time and have proven to work well.
The other thing that I’d like you to add is not to be afraid to develop your own principles and concepts that might make your work easier and better. We all evolve and can bring good ideas to the world. Anyway, I hope this tutorial was helpful to you. If you have any questions, don’t hesitate to ask them in the comments form below.