Using the Flash to pass data from one request to the next.
The Flash is actually a very simple concept. And no, it has nothing to do with Adobe's Flash Player.
The Flash is just a struct in the session
or cookie
scope with some added
functionality. It is cleared at the end of the next page that the user views.
This means that it's a good fit for storing messages or variables temporarily
from one request to the next.
By the way, the name "Flash" comes from Ruby on Rails, like so many other cool things in Wheels.
The code below is commonly used in Wheels applications to store a message about an error in the Flash and then redirect to another URL, which then displays the message in its view page.
The following example shows how code dealing with the Flash can look in an action that handles a form submission.
Here's an example of how we then display the Flash message we just set in the
view page for the edit
action. Please note that this is done on the next
request since we performed a redirect after setting the Flash.
As you can see above, you use the flashInsert() function with a named argument when you want to store data in the Flash and the flash() function when you want to display the data in a view.
The key chosen above is success
, but it could have been anything that we wanted. Just like with a normal struct, the naming of the keys is your job.
As an example, you may choose to use one key for storing messages after the user made an error, called error
, and another one for storing messages after a successful user operation, called success
.
The more you work with Wheels and the Flash, the more that you're going to find that you keep repeating that flashInsert()/ redirectTo() combo all the time. Wheels has a solution for that within the redirectTo() function itself:
That piece of code does exactly the same thing as the example shown previously
in this chapter. The Wheels redirectTo() function sees the success
argument coming in and knows that it's not part of its own declared arguments.
Therefore, you (the developer) must intend for it to be stored in the Flash,
so Wheels goes ahead and calls flashInsert(success="The user was updated successfully.")
for you behind the scenes.
So what if you want to redirect to the edit
action and set a key in the Flash
named action
as well? Simply prepend the key with flash
to tell Wheels to
avoid the argument naming collision.
CFScript
We don't recommend naming the keys in your Flash action
, but these naming
collisions can potentially happen when you want to redirect to a route that
takes custom arguments, so remember this workaround.
Besides flash() and flashInsert() that are used to read from/insert to the Flash, there are a few other functions worth mentioning.
flashCount() is used to count how many key/value pairs there are in the Flash.
flashClear() and flashDelete() do exactly the same as their
counterparts in the struct world, StructClear
and StructDelete
—they clear
the entire Flash and delete a specific key/value from it, respectively.
flashKeyExists() is used to check if a specific key exists. So it would
make sense to make use of that function in the code listed above to avoid
outputting an empty <p>
tag on requests where the Flash is empty.
( flash() will return an empty string when the specified key does not
exist.)
Check out the Controller > Flash Functions section in the API listing of all the functions that deal with the Flash.
Throw the flashIsEmpty() function into the mix, and you might find yourself writing code across your Wheels projects that looks something like this:
All of that above code can be replaced with a single call to the flashMessages() function:
Whenever any value is inserted into the Flash, flashMessages() will
display it similarly to the complex example above, with class
attributes set
similarly (errorMessage
for the error
key and successMessage
for the
success
key).
You can also use flashMessages()'s key/keys
argument to limit its reach
to a list of given keys. Let's say that we only want our layout to show messages
for the alert
key but not for the error
or success
keys (or any other for
that matter). We would write our call like so:
Just keep in mind that this approach isn't as flexible, so if you need to customize the markup of the messages beyond flashMessages()'s capabilities, you should revert back to using flashIsEmpty(), flash(), and other related functions manually.
Earlier, we mentioned that the data for the Flash is stored in either the
cookie
or the session
scope. You can find out where Wheels stores the Flash
data in your application by outputting get("flashStorage")
. If you have
session management enabled in your application, Wheels will default to storing
the Flash in the session
scope. Otherwise, it will store it in a cookie on the
user's computer.
You can override this setting in the same way that you override other Wheels settings by running the set() function like this:
Note: Before you set Wheels to use the session
scope, you need to make sure
that session management is enabled. To enable it, all you need to do is add
this.SessionManagement = true
to the app/config/app.cfm
file.
So what storage option should you choose? Well, to be honest, it doesn't really matter that much, so we recommend you just go with the default setting. If you're a control freak and always want to use the optimal setting, here are some considerations.
Although the Flash data is deserialized before stored in a cookie (making it possible to store complex values), you need to remember that a cookie is not the best place to store data that requires a lot of space.
If you run multiple ColdFusion servers in a clustered environment and use session-based Flash storage, users might experience a loss of their Flash variables as their request gets passed to other servers.
Using cookies is, generally speaking, less secure than using the session
scope. Users could open their cookie file up and manually change its value.
Sessions are stored on the server, out of users' reach.
From CFWheels 2.1, you can now change the default flash behavior to append to an existing key, rather than directly replacing it. To turn on this behavior, add set(flashAppend=true)
to you /app/config/settings.cfm
file.
An example of where this might be useful:
Which, when output via flashMessages()
would render:
With set(flashAppend=true)
, you can also directly pass in an array of strings like so:
In 2.2
upwards:
There are certain circumstances where you might not be using the flash: for example, if you have wheels setup as a stateless API (perhaps in a cluster behind a load balancer) where you're using tokens vs sessions. In this circumstance, you've probably turned off session management, which only leaves cookie
as a viable route. But if set to cookie
, you always get Set-Cookie
being returned, which is unnecessary.
In wheels 2.2 you can now set(flashStorage = "none")
which will prevent the creation of the cookie, and also not try and write to a session.