The Right Way to Edit WordPress Themes

How to properly customize Wordpress based website, where to add your own code, and how to override existing functionality.

480 views

Edited: 2021-05-30 12:22

When working on client Wordpress sites, I have noticed a tendency to make changes to the front-end design all over the place, which makes it harder for developers to work with the site. People often install plugins to change headers and footers, and so on, and the end-result is usually very messy.

The correct way to develop Wordpress based websites is to either create a child-theme to one of the existing themes, or create your own theme from scratch. Changes to the CSS should be added in the child theme's style.css file — let this article serve as a reminder on how to do things properly.

But, ideally you would just make your own front-end or theme for Wordpress, since the themes you find are not always optimized for speed and usability. It is just the nature of the Wordpress ecosystem.

The style.css file is located in the root of the child theme. This is usually wp-content/themes/name-of-child-theme

Note. If you do not understand file system paths, then I recommend reading this article about: Absolute and Relative Paths

The base path of the theme can be obtained using the get_stylesheet_directory() function — but the output is bad because the trailing slash is missing. So, alternatively, you can also establish your own base path; see also: How to Determine the Document Root or Base Path in PHP

Only really complex changes should call for PHP coding, and this can either be done by creating a child theme or by creating your own Wordpress plugin.

Making changes to the PHP code

Of course, if you need to make more complex changes to a Wordpress theme, you may need to modify the PHP code.

Before doing that, you should examine the design or documentation of the parent theme more carefully to determine how to implement your changes. The individual PHP class in the parent theme may be plugable, which means you can easily override it from a child theme. If a class is plugable, it should have something like this at the top:

if ( ! class_exists( 'some_class_name' ) ) :
  some_class_name {
   // The code of the parent theme's class...
  }
endif;

This piece of code makes sure that only one copy of each class is included; if there is another class included already from the child theme, the parent's version of the file will not be included.

To modify the code of the class, you should copy the class over to the child theme's root directory, doing this will allow you to easily include the file from functions.php:

require_once get_stylesheet_directory() . '/some_class_name.php';

Then you can make your modifications to the class located in the child theme.

Note. When making complex changes, such as this, it is nice if you remember to add comments to describe your changes to other developers.

Avoid using Code Snippets and functions.php

When making complex changes and adding new features to a Wordpress site, it may be tempting to add the changes directly in functions.php in the installed theme, or through the code snippets plugin. In reality, these approaches are just wrong and dangerous, since it prevents you from updating the theme without having your changes overwritten. Professional developers aim to do things right from the start — see also: Reasonable efforts in web development

Instead of modifying functions.php in the theme directly, consider either creating your own Wordpress plugin or creating a child-theme.

Of course, if you decide to modify the theme files, you will be using functions.php in the child theme to add your changes. If this is the approach you choose, then you should really organize your changes into individual files to avoid the file getting overwhelmingly large.

Files can be included them with either require, include statements — depending on what is most suitable. Sometimes it may be necessary to use the include_once and require_once functions when developing Wordpress child-themes, this is because a file might otherwise be included several times, which can cause errors.

The require_once and include_once statements

Okay, so first I would just point out the absolute hell of working with file system paths in PHP; this stuff is not easy, and even experienced PHP developers like me sometimes make mistakes. The thing is, even if you forget to add a forward slash after a directory, your include can fail, and it might fail silently if you are not using require — there is no way to know if the build-in methods of a CMS or framework for getting the file system path includes a forward slash — to know, you have to echo the output of the function. If it is not included, then you need to add it yourself. Wordpress does not include it, which is a bad practice!

To make things more confusing, the get_stylesheet_directory() function that is used to get the path for the child theme root has a highly misleading name — this function has nothing to do with CSS stylesheets — it returns the path for the child theme root! Example output:

/var/www/my-site-local-test/wp-content/themes/name-of-theme

Note. that the output comes without a trailing slash "/"; this is actually a bad practice on Wordpress part, since it might lead someone to think that the path is a file rather than a directory.

If you use require instead of include, then Wordpress will simply exit with an error if the path is wrong. This makes it very obvious what the problem is, and it will be faster to find out what is wrong with the path.

If you only use include, then Wordpress will continue to run if it was unable to include the file. When developing child themes, this might mean that the parent class will be loaded instead of the child class, and you will probably not be able to tell why your child class is not overriding the parent as expected. So, unless you got an actual reason to use include, I recommend you stick with require.

Finally, these statements are actually very confusing to developers, since there is also a _once version of include and require statements. The simple difference is that the _once version will only include the file one time, this is useful if the inclusion is taking place inside a loop.

When working with CMS systems in general, it may be a good idea to use the _once version, since you might not know how the system is calling your code.

While developing Plugins for Wordpress, this is something that I have personally had problems with; the problem is easy to debug simply by "echoing" some text from within a plugin file that is included — if then the text is outputted multiple times, it might mean you need to use either require_once or include_once when you include files. When in doubt, always use the require versions of the include functions.

If you are still confused, I recommend you take the time to read this article: Include, Require, Include_once, and Require_once

Organizing your code

Once you understand how to include external files, you will more easily be able to organize your code into multiple PHP files. It can further help to create relevant subdirectories inside of your child-theme folder, and then place the files according to their function.

I personally prefer to just have one big "lib" folder that contains a bunch of subfolders with my files. E.g.:

  • child-theme/lib/newmail/newsmail.php
  • child-theme/lib/contact_form/contact_form.php
  • child-theme/lib/contact_form/contact_form.php
  • child-theme/lib/antispam/antispam.php

These files will then be included from a suitable place (E.g. Composition Root) such as functions.php in the case of Wordpress. If I am using a framework, then this might be index.php instead. Point is, it does not really matter, because it is our job to organize our code in a way so that it is easy to navigate and maintain.

Some organizing is better than no organizing at all. I have seen Wordpress websites that contained single PHP files consisting of thousands of lines mixed with HTML — that is just too large, and it makes it incredibly slow to understand the code for new developers, so please do something to avoid such situations.

Ideally, you should also aim to separate your HTML from PHP. Small bits of HTML is fine, but very large HTML chunks should probably be kept in a form of external templates, even if those templates are just .php files where the HTML is included as a string in a variable. As I wrote before, some organization is better than nothing.

Developing Plugins

I am not going to get too much into the topic of developing Wordpress plugins in this article, if you want to go down the path of plugin-development, then you should check out this article: How to create Wordpress plugins

The advantage of creating a Plugin rather than a child-theme is that you can create the plugin so that it works independent of theme, which enables switching the themes without breaking the introduced features.

Nearly everything you can do in a child-theme is basically also possible from a Plugin.

Tell us what you think:

  1. How to properly remove the title from a Wordpress post, and how to do it for specific post types.
  2. There is no function to select a post by slug name (post name), but we can create our own function to do it; find out how in this tutorial.
  3. How to manually move a Wordpress website to another domain name, and copy the database and the files from the old site.
  4. Should you use Wordfence or Malcare? And are they even sufficient security tools? Securing a Wordpress site with third party plugins and themes is probably harder than you think.

More in: WordPress Tutorials