Programming Talk

WordPress programming: When functions.php is the wrong place for your code

For years, much of my WordPress programming went straight into the functions.php file. If I needed a shortcode, an admin change or a small function for one client, this was where I added it. It was quick, it worked and I did not see any reason to create a separate plugin for every little requirement.

That approach worked for a long time. The website loaded, the new features did their job and nobody looking at the website could tell that the file behind it was becoming bigger with every change.

Then a missing bracket brought the entire website down. That incident made me look at the problem differently. The question was no longer how big functions.php had become. The real question was whether all that code belonged to the theme in the first place.

Why functions.php keeps growing

As demand for new features grows, you keep on adding code to the same file.

In my case, it could be a new shortcode. A small change in the WordPress admin area. A function I wrote to fix a client’s date format. A custom button that added an extra attribute to web pages. A new web page template that couldn’t be obtained from the standard WordPress page creator.

Each function seemed too small to deserve its own plugin, so I placed it in functions.php and moved on to the next task.

Besides, until I started creating plugins for highly specific needs, I thought plugins were written by very cool programmers. They seemed like proper software packages that needed many files, a settings screen and perhaps their own documentation. My small function did not seem important enough.

Of course, a plugin does not have to be large or public. It does not have to be submitted to the WordPress plugin directory either. A plugin can contain a few lines of code written for one website and one purpose. I understood this much later.

Why smaller files do not solve the main problem

When the website went down, the situation was so bad that I could not even access the admin area. My first thought was that I should have divided functions.php into smaller files.

I still believe in writing modular programs. Smaller files are easier to read and manage. You can group related functions instead of scrolling through hundreds or thousands of lines whenever you need to change something. This saves time, especially when you return to the code after several months and no longer remember where everything is.

But smaller files solve an organisation problem. They do not solve the failure problem.

If all those files are being loaded by the theme through functions.php, a fatal error in one file can still bring down the website. The code is now arranged more neatly, but WordPress continues to load it as part of the same theme. One missing bracket or a wrongly written function call can still stop the request before the page is displayed.

This led me to a more useful question: if I change the theme tomorrow, should this feature remain on the website? If the answer is yes, the code probably does not belong in functions.php.

What should remain inside the theme

This does not mean that every function should become a plugin. Some functions exist only because of the current theme, and moving them outside the theme would make the setup more confusing.

There is another problem with adding code directly to a theme that you did not build. A theme update may overwrite your changes. A child theme protects those changes, but it still does not turn site functionality into theme functionality.

I normally keep code inside the theme when it deals with things such as:

  • layout hooks used by that theme
  • template-related functions
  • theme styles and scripts
  • navigation menu locations
  • support for features that the theme itself requires

I still place these functions in separate files when there are enough of them. For example, theme setup code can go into one file and template functions into another. The purpose here is to keep the code readable and make future changes easier.

If a feature should disappear when the theme changes, the code probably belongs to the theme. If it should continue working after a theme change, putting it in functions.php may be the wrong decision.

Why I now create small WordPress plugins

If a feature can work on its own, I usually turn it into a small plugin. It may be a form handler, a report, a custom content tool or a connection with an external service. None of these features should depend on the active theme.

This does not mean that every small function needs its own plugin. Several related functions can go into one site-specific plugin. The aim is to keep related functionality together and separate it from the theme.

A plugin can also contain a fatal error and bring down a website. Moving code from functions.php into a plugin does not somehow make that code safe. The practical difference is that the plugin can be disabled by renaming its folder through FTP. Once WordPress can no longer find the plugin folder, it stops loading that code.

I do not have to start changing the theme while the website is down. I can disable the faulty feature, bring the rest of the website back and then work on the problem separately.

WordPress Recovery Mode can sometimes provide admin access after a fatal error. Still, I make sure that I have FTP or hosting file manager access because Recovery Mode may not help in every situation.

Creating several small plugins does mean maintaining more files. You need to name them properly, keep track of what each plugin does and test them when WordPress or PHP is updated. For a function containing only a few lines, this can initially feel like extra work.

Still, I would rather spend a little more time separating a feature today than search through one giant file when something breaks six months later. The plugin does not need to be fancy. It needs a clear purpose and a way to be switched off without disturbing unrelated parts of the website.

Separating the code helps me handle a failure, but it does not replace testing, backups and version control.

Smaller files make the code easier to read. Separate WordPress plugins make failures easier to handle.