drupal_set_message() Cheatsheet: Variables, links, and formatting
When developing custom modules, it is often helpful to the end-user to print out various messages to alert them to errors or explain what has just been done. Drupal does this all the time - for example, after saving a new node, a green notice is printed to the page letting the author know the article has been saved:
If it's been a while since I've had to do this, I always have to quickly check the Drupal docs explaining the drupal_set_message() function for how exactly to format the message, and how to use variables and links. Well, summarized here is a handy cheat sheet that covers most of the scenarios I typically encounter.
Printing out a simple message
For a message like the 'new article' has been created, we just need a simple message, no variables, no links.
Right:
// Message without any links. drupal_set_message(t('Here is our translated string without any links.'), 'status');
Note we are running this through the t() function. This means that the string will be available for translation if needed at a future date.
Wrong:
// Message without any links. drupal_set_message('Here is our translated string without any links.', 'status');
If we had just done this, the string wouldn't be available for translation.
Printing a message with links
If we want a link in our message, for internal paths we can use the relative URL, but external paths use absolute URLs.
// Message with external link. drupal_set_message(t('Here is an external link to <a href="http://google.com">Google.</a>'), 'status');
Make sure to use the double quotes in the anchor, rather than single quotes. If you use single quotes it will interpret that as the end of the string to be translated.
Printing a message that contains variables
Now we're getting to the fun part. Often for custom messages we will want part of the message to change depending on what happened. That's where we can use variables. In this example, we'll print the current month.
We're using the '@' notation to let the t() function know we are passing it a variable.
// Get the month using the PHP date() function. $month = date('F');
// Message with variable. drupal_set_message(t('Message with a variable: The current month is @month.', array('@month' => $month)), 'status');
Why use '@'? Because Drupal makes sure nothing harmful can be put into that variable by passing it through the check_plain() function. More on this next.
What's the deal with '@', '%', and '!'
The Drupal docs concerning the format_string() function cover this in more detail, but here are the basics.
The '@' is what you typically default to if you don't need any special formatting or HTML, because the '@' will pretty much completely sanitize your variable. This is for the first example above where we want a linked variable. ( I know in these cases we don't need to use variables, since we are just using simple strings. But just imagine a simple extension of this example where the @link-text variable may change depending on what has just happened.)
// Example using '@'. drupal_set_message(t('Message with a linked variable: Check out this Tumblr <a href="http://foodonmydog.tumblr.com">@link_text</a>.', array( '@link_text' => 'Food on my dog', ) ), 'status');
If you want to get fancy and have some of your text italicized, you use the '%' notation. In this example 'Cat Cosplay' will be italicized.
Right:
// Example using '%'. drupal_set_message(t('Message with a linked italicized variable: Check out this Tumblr <a href="http://cat-cosplay.tumblr.com">%link_text</a>.', array( '%link_text' => 'Cat Cosplay', ) ), 'status');
Wrong:
drupal_set_message(t('Message with a linked italicized variable: Check out this Tumblr <a href="http://cat-cosplay.tumblr.com">@link_text</a>.', array( '@link_text' => '<em>Cat Cosplay</em>', ) ), 'status');
If we tried the wrong example above, this is how it compares to the right way to do it. If we stick with the '@', the HTML is just printed as plain text. The '%' notation formats the text as italics for us using the drupal_placeholder() function.
Lastly, if we need to use other HTML markup in our message we can use the '!' notation. Use this with caution! As the Drupal docs note, this text will be
'Inserted as is, with no sanitization or formatting. Only use this for text that has already been prepared for HTML display (for example, user-supplied text that has already been run through check_plain() previously, or is expected to contain some limited HTML tags and has already been run through filter_xss() previously).'
Here is where how to make the word 'standing' bold.
// Example using '!'. drupal_set_message(t('Message with a variable that contains limited HTML tags: Check out this Tumblr <a href="http://goatsstandingonthings.tumblr.com">!link_text</a>.', array( '!link_text' => 'Goats <strong>standing</strong> on things', ) ), 'status');
This is a really simplistic example, and in general it's probably best to default to just use the '@' and '%' for formatting - let Drupal do the security work for you!