Wednesday, April 21, 2021

How to Include and Require Files and Templates in WordPress

How to Include and Require Files and Templates in WordPress

When it comes to PHP, a lot of developers love the language, a lot of the developers hate the language, and a lot of developers generally just use it to get their work done.

For what it's worth, I'm of the latter camp. I think PHP is fine. Like anything, it's not without it's problems, but I enjoy working with it well enough and see it as a way to get work done versus some pie-in-the-sky language for some time of utopia of development.

The thing is, one of the things that developer's love about PHP—its features and flexibilities—are the very things that often trip us up. The list is long, but in the WordPress world, one of the most common points of confusion is the proper way to include external files.

PHP offers four ways to do this and WordPress even offers its own variation thereof.

In this article, we'll survey the four ways that PHP offers to include files, guidelines for when to use each, and we'll review WordPress' features for including files.

Including Files With PHP

Generally speaking, including files with PHP refers to the action of including another script into the context of the script on which you're currently working.

You can think of this as importing a file such that when the file is returned from the server, the scripts are combined together in the order that they are included, and then interpreted as a single file.

First, we'll look at the ways to include files in PHP and the implications of each. At the end of the article, we'll review when we should be doing this.

Using include()

According to the PHP manual:

include() will include and evaluate the specified file. If the file isn’t found, a PHP warning will be thrown.

Simply put, this means that PHP will look to the file that you're attempting to include. If it's found, then it will be added to your script in the exact place that you've declared it.

This is important to understand. For example, let's say you're writing a set of functions that depend on a prior set of functions. In that case, you'll need to make sure the other file is included first.

On the other hand, if you're looking to bring in a set of functions or an external file in the middle of an existing function, then you can include it exactly in the place that you need it.

Secondly, note that if the file is missing, PHP will throw a warning. Depending on the server configuration, you may see this rendered to the browser or you may see this written to a log file (or both).

Nonetheless, warnings are just that—they aren't considered fatal and typically don't stop execution, but they are important to note because it generally implies that part of your work is not being properly loaded and/or interpreted.

Finally, note that when a file is loaded using include() that it will have access to all of the variables previously defined in your existing script.

For example, say that you're working on a function and halfway through the function, you're going to include a separate file. That separate file will have access to the variables defined earlier in the function in which it's included.

Although you may view this as convenient, it makes the external script a bit unclear as it doesn't necessarily show that it's depending on variables defined externally. This can be confusing especially when working with a team.

Using include_once()

Taken directly from the PHP manual:

include_once() will perform the same behavior as include() but won’t include the file again if it’s already been included.

Obviously, there's no need to spend as much time talking about the general points of include_once(), but there are some key differentiators between how include_once() works and how include() works.

First, whereas include_once() performs largely the same as include(), it will not allow you to include the script again. This means that if somewhere else in your project, an external file has been included, that's the definitive location in which that file has been included.

So what's the advantage of this? Aside from assuring that there's only a single place in which a script is included, it also ensures that variables and functions won't necessarily be redefined. Recall that when using include(), scripts have access to functions and variables that are defined above them.

If you opt to define a new set of variables or functions in a file, include it in another script, and not use include_once(), then you run the risk of re-defining functions and variables potentially causing major problems with the execution of your code.

Requiring Files With PHP

Requiring files is similar to including files in that it's another way that you can include a script into the script that you're currently writing, but it carries a set of its own implications around errors and security.

Though you can consider the act of requiring a file in much the same way that you can including a file, it does carry the implication that it's stronger—that is, the external file is required for execution.

As we'll see, this is exactly this case.

Using require()

Once again, straight from the PHP manual:

require() performs the same as include() but will throw a PHP fatal error if the file isn’t found.

So here's the thing with require(): it will perform the same action as include() as far as importing the external script into the context of the one on which you're working, but if it fails to locate the file, it throws an error and completely halts execution.

This means that your application stops. With include(), you'll get a warning and it will attempt to keep going.

On some level, it may seem like requiring files is the right way to go. After all, why would you want to risk including something just to have a warning with a potential failure in the application.

But it all comes down to the nature of what you're working on. Sometimes, simple PHP warnings are okay—like forgetting to initialize the index of an array—other times, you need an error.

There aren't hard and fast rules for when to use this versus includes, but think critically about the nature of what you're doing and the implications that it carries if it were to fail.

Using require_once()

Lastly, from the PHP manual:

require_once() performs the same as require() but will not include the file a second time if it’s already included.

This is possibly the easiest to understand since we've covered the last three functions in relative detail. Simply put, require_once() performs the exact same functions as require, though it will not attempt to include a file again if it's already loaded in your script.

Rules of Thumb

In addition to critically thinking through which function is best for the nature of your project, here are two additional rules of thumb to consider when working with include() and require():

  • require_once() is better for larger sites as it does some additional work at the lower level that impacts security and performance
  • include_once() is faster and is generally deemed acceptable for smaller sites

Easy enough, but what about WordPress helper functions?

Including Files Across Directories

Things can get confusing when you are working on a project with many files spread across multiple directories. Remember that the paths of files you want to include are resolved with respect to the immediate parent file.

For example, consider the following directory structure.

Here is the code inside the header.php file:

Here is the code inside the functions.php file:

And here is the code inside the share.php file:

When you are starting out, it is common to think that the code for share.php will throw an error because functions.php is not located in the same directory as share.php. However, the require_once("functions.php") statement is inside headers.php, so the interpreter will look in the directory that headers.php is in for the functions.php file.

This is because PHP will parse functions.php in the context of header.php. Since they are both located in the same directory, the function will be included in our file as expected.

Variable and Function Scope With Included Files

When you include a file inside a parent file. The scope of variables defined in the included file will be the same as the variable scope at that particular line. However, any functions and classes that you have defined in the included file will have a global scope. Let's understand it through an example.

Our first file called inc.php has the following code:

Our second file called main.php has the following code:

We defined a variable called $current_day inside our function current_date(). So, it won't be accessible in our main file as its scope is limited to the current_date() function. On the other hand, the current_time() function defined inside current_date() is accessible to us because it has a global scope.

You should consider reading understanding variable scope in PHP to learn about variable scope in PHP.

Including Files With WordPress

With all of that said, there are better ways than using include() and require() to include templates in your WordPress projects.

Say, for example, that you have several loop files, including one for a post format:

  • loop-standard.php
  • loop-image.php
  • loop-quote.php

And you need to include them in single.php whenever you're working on a theme's single post page.

At one point in time, it was acceptable to do something like this:

But that's no longer the best practice.

Use get_template_part()

WordPress now offers a function, get_template_part(), that is part of the native API and is used specifically for reusing sections—or templates—of code (except for the header, footer, and sidebar) through your theme.

The function accepts two arguments:

  • The first argument is the slug for the template. In the example above, that would be loop.
  • The second argument is the name of the template. In the example above, that would be standardquote, or image.

In sticking with our example above, let's say that we're in The Loop and we want to include the quote post format template. In that case, we'd do the following:

Or, assuming that you've named your templates to match the post format types, you can do something even cleaner:

Clean, right?

You can actually take this a step farther. Let's say you've abstracted your pagination code out into its own template file called pagination.php. Using get_template_part(), you can include this across your entire site in, say, footer.php or in index.phpsingle.phparchives.php, etc. simply by adding:

Much easier, isn't it?

When Should I Use What?

So after all of this, we still have yet to actually discuss the guidelines of when to use what. By no means am I an authority on this, but here are the rules of thumb that I follow:

  1. In theme development, I always use get_template_part().
  2. In plugin development, I almost always use include_once() and I generally use it once in a function. You can see this in my boilerplates.
  3. If the plugin I'm writing is going to be used on a very large site, then I use require_once().

That's all!

Further Reading

For more detailed explanations of what was covered in this article, be sure to read the manual pages for each of the functions:

This post has been updated with contributions from Monty Shokeen. Monty is a full-stack developer who also loves to write tutorials, and to learn about new JavaScript libraries.


No comments:

Post a Comment