SMARTY: Assigning variables to the header from the body

The problem recently presented itself to me when writing some new functionality for revealCMS: I needed to set some variables to load in the page head, but could only be set after a portion of the body had completed rendering. I wrote a plugin that essentially loads a different stylesheet depending on the input of the Smarty template function. The hard part wasn’t assigning the variable – it was figuring out the best way to get that assigned data to appear in a part of a page that had already been rendered – the head.

It makes sense why Smarty would work this way – that you can’t go back and re-assign variables. It would be too messy. So somehow you need to assign the variable first in the body, then go back and render the head. It’s simple… really. Believe it.

But why bother? Why not put <style> tags directly into the page body where the plugin is located? The reason is simple: <style> tags (and <script> tags, for that matter) MUST be in the page header. It’s a web standards thing.

First, break-up your page templates into two sections: the header (containing everything before the <body> section of your template), and the body, which contains the <body> section. First render the body using
$body = $smarty->fetch('body.tpl');
At this point, I’ll just assume that your page functions have loaded and you’ve either placed an {assign} tag somewhere in the template, or you’ve used a $smarty->assign() inside the template function. If you’re not familiar with $smarty->fetch(), it’s just like $smarty->display(), except it outputs the contents to a variable rather than the screen. And just like display() it can also take $compile_id and $cache_id as optional parameters.

Now render the head:

$head = $smarty->fetch('header.tpl');
By this point everything should work-out as we expect it. Our dynamically loaded css file is loaded in the head and our standards friends are happy. The beauty about this example is that you can now render a number of items in any order you need them then display properly, so long as it makes logical sense.

Here’s a tip: You can use this method to dynamically load javascript files and frameworks if your fancy web 2.0 page functions/plugins need it at some times, but not at others.

Join the Conversation

9 Comments

  1. Hi, my problem is little similar, i explain, i want to join smarty and flash actionscript in a banner but the problem is we can t load variables comming php files, Because php files need smarty files to be display, Can you think we can load smarty variables in actionscript,
    thanks for help

  2. It’s actually fairly simple. According to Permadi.com you simply attach a query string to the end of the filename within the object and embed tags. Otherwise you can always go the route of creating a separate XML file (Smarty can do that too) and loading that.

  3. May I also suggest registering a custom template function that automates so you can make life a little easier e.g.

    Adding something like
    {add_head_tag type=”script” src=”javascriptfile.js”}
    {add_head_tag type=”script” src=”otherjavascriptfile.js”}
    {add_head_tag type=”css” src=”cssfile.css”}

    To your “body” template file and just have

    {foreach from=$stylesheets item=src}

    {/foreach}
    …same for scripts….

    Within the header template file.
    Thanks for the article though, it is what got the thought processes going to write the function in the first place, didn’t want to post the custom function because your blog page would grow downwards a little too much 🙂

    1. Hi Cameron, Any chance we could see that code? I don’t think anyone would mind if the page got a little bit longer 😉

  4. The simplest solution to this is to call all of your plugins, create all of your variables etc. at the top of the template. i.e:

    {assign var=’title’ value=’My Title’}

    {$title}

    {$title}
    This is your content

    That said… it’s not always possible, or ‘clean’ to do that. so CMSMS actually does the same thing (by default) parses the template into parts, and processes the body stuff first, then the head stuff.

Leave a comment

Hey there! Come check out all-new content at my new mistercameron.com!