Temporary Options in WordPress: Our Best Option?

When it comes to programming, the idea of temporary values or temporary variables or any way of storing data temporarily in memory isn’t anything new.

But when working with WordPress – which is stateless – we don’t always have that luxury. That is, it’s not simply a matter of, say, throwing something into the current session, reading it, and then removing it when we’re done with it.

And that’s when I’ve been giving more and more thought to the idea of temporary options, for lack of a better term of course. That is, whenever I need to store a value from a single page load, or request, to read in another page load, or another request, I’ll temporarily throw the value into the options table.

Temporary Options: An Exercise and Representation via  Rudimentary Sketching
Temporary Options: An Exercise and Representation via Rudimentary Sketching

Is that sloppy? Maybe. Do we have a lot of other choices? It depends on how much of modern browser technology we want to use. That’s not the point of this post, though.

The point is that because of the way WordPress works, I wonder if our current, best strategy for maintaining temporary values that is most widely supported across installations is to temporarily add a value into the options table, read it, and then delete it once it’s been retrieved?

Our Options for Temporary Options

Personally, I don’t have a strong opinion on if this is a bad thing or not. If it’s the nature of how the foundation on which I’m working on a solution works, then I’ll go with it.

So, first, this is how I’ve typically done this within WordPress:

1. Creating a Temporary Option

First, I set up a function that’s hooked to update_option. This allows for looking at the option that’s being updated, its old value, and its new value.

In the function, I can look and see if a specific option is being saved. If not, then I can just ignore it; otherwise, I can take a look at it and begin working with a temporary option.

But what would the temporary option hold?

2. An Option For Temporary Options

Say you have an option in a plugin that is toggled. Perhaps it requires the user to input some information before moving throughout the rest of a process.

Case in point: Say you’re working on a checkout experience and you want to force users to create an account, but there’s an option that allows for customers to checkout without a creating an account.

One implementation we could use is this:

  1. Before the checkout page is loaded, look to see if the user can checkout as a guest.
  2. If so, store the original value of the option in a temporary option.
  3. Change the original value so that it requires they create an account.
  4. Once the checkout process is done, then copy the value fro the temporary option to the original option.
  5. Delete the temporary option.

It’s similar to the whole exercise in C when you need a pointer to swap two numbers (for whoever remembers or whoever has done that).

Our Best Option?

The process outlined above is but an example and isn’t meant to be the definitive way to maintain temporary values. Secondly, the checkout example isn’t meant to associate this post with eCommerce.

Instead, it’s meant to provide a concrete use case for when storing temporary options is useful and how we may want to do it.

So the original question remains: Given the way WordPress works, the lack of sessions, and without being guaranteed certain browser features like localStorage, are temporary options in the options table our best way to go?

19 Replies to “Temporary Options in WordPress: Our Best Option?”

  1. Through the entire article, I expected some talk of WordPress Transients since they’re provided by WordPress exactly for this purpose.

    Transients according to the codex should be used in lieu of options to store any data that is temporary or expected to expire.

    I use transients instead of options in these type of scenarios. Pippin Williamson even offers a great free utility for managing then called “Transients Manager” on the WP plugin Repo.

    1. Through the entire article, I expected some talk of WordPress Transients since they’re provided by WordPress exactly for this purpose.

      This is a good point – and it’s not that I’m unfamiliar with transients, but I’ve evidently done a poor job of communicating what I’m trying to convey.

      Transients according to the codex should be used in lieu of options to store any data that is temporary or expected to expire.

      Transients are usually used for caching data, for making it available for caching or setting a time in which you want to explicitly expire it. (All of this is here).

      Everyone seems to misunderstand how transient expiration works, so the long and short of it is: transient expiration times are a maximum time. There is no minimum age. Transients might disappear one second after you set them, or 24 hours, but they will never be around after the expiration time.

      And transients are stored in the options table. Ultimately, the point I’m working toward is not a matter of how to cache data for a pre-determined amount of time. It’s to store it until a time that I need to swap information out and then delete it.

      I opt for the manual case because I know during which request and at which point during the lifecycle I’m ready to retrieve and remove it. Transients aren’t intended for that.

      1. Except that transients are not stored in the options table when you have a persistent object cache, like memcached or redis. And that’s why they can disappear the instant you create them, if there’s something filling the object cache and pushing other data out of it too quickly.

        Transients truly are only good for caching data that can be recreated, period. You are right to not consider them for data that you need to rely on being there later.

        1. Except that transients are not stored in the options table when you have a persistent object cache, like memcached or redis.

          This is true and I appreciate it! (though it’s getting way off the origin intent of this post – the comments have lead us here, though, and that’s fine! :)

          Transients truly are only good for caching data that can be recreated, period. You are right to not consider them for data that you need to rely on being there later.

          Thanks — I think your comment probably did a better of conveying the purpose of the post and my original post did.

    1. I would have thought that the transients API is more appropriate for this kind of temporary data caching.

      For temporary data caching, that’s exactly right. See a more detailed response from me in this comment.

      I could’ve done a better job of explaining a use case, I think :).

      Though it’s similar to the options API there is more flexibility with it including integration with WP caching plugins.

      This is true, but you can also set your options to take advantage of caching by dealing with the $autoload argument. I’ve written about the object cache in this post.

      For the use case outlined, it’s not terribly useful to have it available in the cache unless the cycle of time is that long or impacts performance that much.

  2. Good food for thought, Tom.

    I can think of other possibilities but with limits depending on the particular situation.

    For example, passing a URL query string could work but only if you’re refreshing the page, if the data is not sensitive so it can visibly appear in the URL, and if it wouldn’t hurt anything if someone messed with the URL and changed that data. (Leaving encrypted query strings out of the discussion for now.)

    Likewise, setting a cookie could work with the same stipulation of the data being visible and safe if manipulated. The system would also have to function if someone’s browser is rejecting cookies and it doesn’t get set.

    So a temporary option seems like a great choice when the detail has to be kept behind the scenes.

    One other consideration with setting a temporary option is what happens if the process isn’t completed to remove the option. Do we have to build a cleanup mechanism? Or should we at least set $autoload to false on that option so it won’t be forever retrieved on every page load if left hanging around?

    1. I can think of other possibilities but with limits depending on the particular situation.

      Yeah — it’s hard to nail down a specific “all-in-one” solution (which I don’t really believe exists) to capture a variety of uses cases.

      For example, passing a URL query string could work but only if you’re refreshing the page, if the data is not sensitive so it can visibly appear in the URL, and if it wouldn’t hurt anything if someone messed with the URL and changed that data. (Leaving encrypted query strings out of the discussion for now.)

      Likewise, setting a cookie could work with the same stipulation of the data being visible and safe if manipulated. The system would also have to function if someone’s browser is rejecting cookies and it doesn’t get set.

      Fully agree on both accounts!

      So a temporary option seems like a great choice when the detail has to be kept behind the scenes.

      I think it’s also useful when you want to ensure that it’s safely stored somewhere that can be easily managed by a given API.

      One other consideration with setting a temporary option is what happens if the process isn’t completed to remove the option. Do we have to build a cleanup mechanism?

      I would say yes. There would need to be something in place to look and see if the key/value pair exists in the database and if the data is out of sync (which is easy to tell based on looking at the option from which we copied the original value), we’d sync them up then delete it.

      Or should we at least set $autoload to false on that option so it won’t be forever retrieved on every page load if left hanging around?

      I like to set that to true to make it available for caching purposes, but having an explicit check (or expiration which some other commenters have noted) to remove it so it’s not basically just orphaned in the database. That’s a whole other problem with certain things in WordPress.

    1. I’m not a fan of them…

      • they don’t adhere to object-oriented programming (which is what I prefer to use),
      • you generally have to know the global state of the application before using them,
      • many times, an application can’t exist without the availability of that piece of code,
      • it’s harder to unit test
      • and other reasons :)
    1. Sure! Even though sessions are intended to help us preserve information across different page loads (the same page or not), theya re usually related to a person being logged into an application.

      If you’re building a plugin and it includes that type of functionality, I’m actually not against that, but I do think that it requires a full and proper understanding of how to leverage sessions, relate them to WP architecture (which can be weird, at times), and then also how to properly destroy things when you’re done.

      The short answer to the whole thing is: If you know how to properly implement and architect sessions, go for it! But if you’re someone who’s stumbled across session_start and then are just tossing things into $_SESSION, it might cause some unforeseen problems.

      1. It would be great if you can write a dedicated post about WP and its session handler. Basically, when I use session in WP, I don’t mix it with the WP session and try keeping it a separated thing. And that works.

  3. Hi Tom,

    forgive me if I’m coming late but I’ve seen this article only now. You’ve proposed an interesting solution but IMO there’s a problem. If the website is popular and with many visitors there’s the risk that two users overwrite each other data if they are using the same page at the same moment. The solution would be to make the meta key unique for example by attaching the user id to the key name but this works only with logged in users

    1. This is a good question because what you’re describing is a race condition and it can happen, though it usually happens of sites with much, much higher traffic.

      There are a few different ways to handle. For instance, like you mentioned, coming up with a unique key. To do this, you and use any number of different variables – a random number, a timestamp (using milliseconds), using part of the information stored in a server variable, etc.

      The gist of the post remains the same, but just how far you want to take the uniqueness of the key depends on the nature of the site.

  4. I’m starting to think that using a custom post type for this sort of temporary storage might be a better solution. Once it’s registered with public => false, it has the following benefits:

    Permanent storage
    Cacheable
    Easily queryable with better SQL indexes
    Already includes fields like author ID and date created that may be useful
    Doesn’t clutter the options table
    Multiple post meta values, if that’s needed

    1. Being totally honest, I was willing to write this off because I think “CPTs way too heavy for something like that.” But then the more I thought about some of your points, I thought “If it was all of the above minus the ‘view’ (being the front-end of the CPT) then it’s actually a pretty good point.”

      To that end, this has me thinking about this topic again.

      I don’t think it has to be either/or, to be clear, but I think depending on the nature of the problem might dictate which route is taken.

      Good stuff, Pete.

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.