Partial Page Caching and Smart Template Parts with Pods

pods_view() can be used in a similar way to the WordPress function get_template_part(), but provides advanced options including the ability to utilize Partial Page Caching to cache the included output into the object cache or transients to improve performance. It can also pass data, such as all or part of your current $pods object to them. There’s also a helpful filter that allows you to override what’s returned for any instance of pods_view(), which is one of the reasons Pods core uses it for it’s field type inputs and other admin / front-end views.

What Is Partial Page Caching?

Most of the time when we talk about caching in WordPress we are referring to page caching. Page caching  saves page load time by creating static copies of pages in a WordPress site, so your server doesn’t have to run all of the various queries that go into building a page every time it is loaded. Page caching is the right tool for any site that only changes when a post is published or some change is made to the site’s appearance, which triggers the page cache to rebuild itself.

For more dynamic sites, for example sites that generate lots of data specific to the currently logged in user, page caching is not a great solution. A good example of a type of site that is ill-served by page caching, is a membership site. Whole/full page caching for logged-in users would mean that “Bill” could see the header of the site and it could say “Welcome, Max” which can lead to a whole slew of bad things including privacy concerns.

Chris Lema wrote an article on performance considerations for membership sites that advocates partial page caching, also known as fragment caching. The article provides a great non-technical introduction to partial page caching that I highly recommend, as well as some links to more technical articles on it.

Parameters For pods_view()

function pods_view( $view, $data = null, $expires = false, $cache_mode = 'cache', $return = false )

The function pods_view() has only one required argument, the file to be included. The file is assumed to be in the theme directory or child theme directory if no path is specified. You can also specify a full path to a file in order to use a file from a plugin file.

pods_view() can pass a set of variables into the template part it is being used to include. This allows you to use a single Pods object, WP_Query object or some other data in both the dynamic, non-cached part of a page and in the cached portion. By using this functionality you can avoid using global variables that can create other types of issues. Use the syntax compact( array( 'your_var_name' ) ) for an easy way of passing the variables through, they will be automatically scoped to the included file.

When you set an expiration time in seconds for the third parameter, the default is for pods_view() to use the WordPress object cache. Object caching is usually the best choice, but there are other options such as ‘transient’, ‘site-transient’, or ‘options-transient’. Set the third parameter to “0” (zero) to cache it indefinitely, or false to disable caching (default).

Keep in mind that WordPress has pre-defined constants for various units of time in seconds, such as ‘HOUR_IN_SECONDS’. You can see the full list of these constants in the codex. The object cache is not persistent and will expire at the end of a request unless a persistent cache plugin is installed. I will cover this more fully at the end of this tutorial.

In general you will usually want to use pods_view() to echo the file it is including and that’s the default behavior. By setting the final argument $return to true, the output will be returned as a string which allows for further processing before outputting, or for it to be stored in a variable and reused later.

Be sure to check out the documentation page for pods_view as well as the source for the class itself.

Example Uses

Using Pods View to cache and output an RSS feed include

In a highly dynamic page that has some part of it generated by an outside source, for example an RSS feed, the outside data can be a major factor on page load times. This examples allows a page to include an RSS feed, included in its own file, that is regenerated every hour instead of on every page load. You can get around loading the external data by using transients or object caching, but this method will also handle all of the processing and markup build process too.

pods_view( 'rss-feed.php', null, HOUR_IN_SECONDS, 'transient' );

Note that transient caching must be used to maintain the cache after the request is finished, unless you have a persistent caching plugin installed.

Using Pods View as a Partial Page Cache

pods_view(), which can be used with any type of WordPress data, not just Pods data, is an easy way to section off the less dynamic parts of a otherwise highly dynamic page into a separate template part that can be cached. This reduces the demands on your server, allowing it to more quickly run the database queries for the rest of the site.

A basic example of moving a secondary WP_Query request and caching the content can be seen below, in a Before / After example, with the new WP_Query request going on in the new file, which can now utilize Partial Page Caching.
[gist id=”8051967″ file=”2-template-before.php”]
[gist id=”8051967″ file=”2-template-after.php”]
[gist id=”8051967″ file=”2-content-most-commented-on.php”]

Some WordPress template files have a very small amount of user specific data that makes them incapable of using page cache when the majority of the page could be cached. For example, you might want to show posts that are of the most interest to the current user as featured posts, using categories that the user set as favorites, followed by a regular WordPress loop. Here is an example template to accomplish this:
[gist id=”8051967″ file=”3-template-before.php”]

The query for favorite posts must be generated based on the logged in user and is omitted for users who are not logged in making page caching impossible. By moving the that block into it’s own file and caching using Cache Keys, we can cache that list of category posts based on the user’s categories. If other users have those same favorite categories, that loop won’t have to be re-run or content rebuilt.
[gist id=”8051967″ file=”3-template-after.php”]
[gist id=”8051967″ file=”3-content-fav-category-posts.php”]

Output Buffering is built-in

With get_template_part(), you had to hack around the content include and use output buffering, which isn’t very complex, but is also prone to error for new developers.

pods_view() includes a 5th parameter called $return which you can set to true to return the content instead of the default of automatically echoing onto the page. This is useful if you want to apply filters, evaluate shortcodes, or replace custom template tags in the generated content.
[gist id=”8051967″ file=”4-after.php”]

Cache Keys and caching content from a template based on a variable

By default, when you use pods_view() caching, it will return that same content anywhere in your theme that you call that cached file. To get around this and to differentiate the file in different ways on different pages or parts of the theme, we’ve built Cache Keying into Pods 3.0. It works by appending a ?query or #hash to the file name, with how you want the cache grouped. For example, you can use the same restricted content include but cache it based on the user role.

Which Cache Method To Use

pods_view() supports four options for caching, which are only utilized if $expires is not false.

  • ‘cache’ (default) uses the WordPress Object Cache (further augmented by Persistent Caching plugins) to store the content in memory
  • ‘transient’ uses the WordPress Transients API to store the content in the database (which uses the Object Cache if a Persistent Caching plugin is active), you normally won’t want to use Transients for template includes that are large, though the object cache is generally the better option in most cases
  • ‘site-transient’ uses the WordPress Transient API to store the content in the database for the whole WordPress network (When WordPress Multisite is configured)
  • ‘option-cache’ is new to Pods 2.3.x and operates like an actual option, but can expire like a transient. The difference between the Transient API and this cache type is it can avoid being deleted if a callback returns false (content could not be retrieved) which keeps content still showing even if there was an issue getting the template built. Callbacks are not utilized by pods_view() itself currently, so it will function no different from Transients if used. It exists as a new option for use via new functions pods_option_cache_set( $key, $value, $expires, $group ) and pods_option_cache_get( $key, $group, $callback )

Different Expirations for Different Folks

If a different expiration is needed for a logged in user versus an anonymous visitor, pods_view() has that covered too, with Advanced $expires handling.

More Information About Partial Page Caching

Towards a Partial Page Templating System in WordPress by Zack Tollman
Fragment Caching In WordPress by Mark Jaquith