Part of the EllisLab Network

Blog & News

Derek Jones
Chief Technology Officer, EllisLab, Inc.

Behind the Curtain Part II

I have intimated before that from my time doing support for ExpressionEngine that I regularly noticed users not taking advantage of some of the simplest of features of ExpressionEngine.  In the Jambor-ee interview for example, I said that my “favorite” feature is the oft-unused custom status feature.  I find them to be simple and straightforward ways of adding metadata to an entry either for establishing a workflow, or as another efficient way for the weblog entries tag to control output.

But Part II of Behind the Curtain is going to go even more basic than that.

I like working smarter and not harder, and this is especially important when you have more than one person building a site.  To that end, if you have not already made them so, Template Global Variables should be your new best friend.  Consider the base template we use for every page:

{html_head}
    
<title>Page Title | ExpressionEngine</title>
{favicon}
{stylesheets}
{js}
{metatags}
{reverse_links}
{html_head_end}

{masthead}

<div id="header">
{embed="global/login"}
    {header_logo}
</div><!-- end #header -->

{embed="global/sitemap"}
{embed
="global/simple_search"}
{embed
="global/site_nav" loc="location"}

{wrapper_column_open}
            {embed
=templates/pageNav}

            
<div id="content">
            </
div><!-- end #content -->
            
{wrapper_column_close}

{embed
="global/footer"}

{embed
="global/copyright"}

{html_close}

The title, loc variable for the main navigation template which I described in Part 1, and whatever goes in the “content” div are the only things one needs to worry about when adding a new page.

The embeds I hope you are already using for common content anyway.  The choice of whether to use an embedded template or a Template Global Variable is rather easy: if you need to use ExpressionEngine tags or PHP, then you need an embedded template.  But if not, Template Globals are incredibly efficient, and still let you affect site-wide changes by modifying things in one place.

If instead of Template Globals, we were cutting and pasting all of our markup to each template, the base template would be:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"
>
<
html>
<
head>
    <
meta http-equiv="Content-type" content="text/html; charset=utf-8" />
    <
title>Page Title | ExpressionEngine</title>
    <
link rel="shortcut icon" href="/images/design/favicon.ico" type="image/x-icon" />
    <
link rel="home" href="http://expressionengine.com/" title="Home" />

    <
link rel="stylesheet" href="http://expressionengine.com/index.php?css=global/global.css" type="text/css" media="screen, projection" charset="utf-8" />

    <!--
[if IE 7]>
    <
link rel="stylesheet" href="http://expressionengine.com/index.php?css=global/ie7.css" type="text/css" media="screen, projection" charset="utf-8" />
    <!
[endif]-->

    <!--
[if IE 6]>
    <
link rel="stylesheet" href="http://expressionengine.com/index.php?css=global/ie6.css" type="text/css" media="screen, projection" charset="utf-8" />
    <!
[endif]-->
    <
script src="/js/jquery.js" type="text/javascript" charset="utf-8"></script>
    
<script type="text/javascript">
        $(
document).ready(function() {
        
        
// toggles the slickbox on clicking the noted link
          
$('a#sm_toggle').click(function() {
            
$('#sm_outer').slideToggle(400);
            return
false;
          
});
        
        
});

</script>
    
<!--[if lt IE 7]>
    <
script defer type="text/javascript" src="/js/pngfix_map.js"></script>
<![endif]-->

    <
meta name="MSSmartTagsPreventParsing" content="true" />
    <
meta http-equiv='expires' content='-1' />
    <
meta http-equiv='pragma' content='no-cache' />
    <
meta name='robots' content='all' />
    <
meta name='description' content='ExpressionEngine: Publish Your Universe' />
    <
meta name="keywords" content="EllisLab ExpressionEngine PHP CMS Content Management System plugins modules business forums gallery weblog blogging software" />
    <!--
Reverse Links from EllisLab network sites -->        
    <
link rev="codeigniter" href="http://codeigniter.com/"
    
title="Code Igniter: Open Source Web Application Framework that makes writing kick-ass PHP programs simple as apple pie" />
    
    <
link rev="pmachinepro" href="http://pmachinepro.com/"
    
title="Flexible and free blogging system that supports advanced features like multiple blogs, moblogging, and much more" />
    
    <
link rev="ellislab" href="http://ellislab.com/"
    
title="Where Ideas Hatch" />
    
    <
link rev="enginehosting" href="http://enginehosting.com/"
    
title="High performance web hosting" />
<
link rel="alternate" type="application/atom+xml" title="Master Atom feed" href="http://expressionengine.com/feeds/atom/full/" />
<
link rel="alternate" type="application/rss+xml" title="Master RSS feed" href="http://expressionengine.com/feeds/rss/full/" />
</
head>

<
body>

<
div id="masthead">
<
a href="http://ellislab.com/"><img src="/images/design/ellislab_network.gif" width="293" height="23" alt="Part of the EllisLab Network" /></a>
</
div>


<
div id="header">
    
{embed="global/login"}
    
<h1><a href="http://expressionengine.com/" title="ExpressionEngine"><img src="/images/design/ee_logo.gif" width="227" height="88" alt="ExpressionEngine Logo" /></a></h1>
</
div><!-- end #header -->

{embed="global/sitemap"}
{embed
="global/simple_search"}
{embed
="global/site_nav" loc="location"}

<!-- Candy comes in a wrapper -->
<
div id="wrapperWit">
    <!--
Hard candy outer shell -->
    <
div id="shell">
        <!--
Gooey center -->
        <
div id="gooey">

            
{embed=templates/pageNav}

            
<div id="content">
            </
div><!-- end #content -->
            
        
</div><!-- end #gooey -->
    
</div><!-- end #shell -->
</div><!-- end #wrapperWit -->

{embed="global/footer"}

{embed
="global/copyright"}

</body>
</
html>

All of that HTML adds distraction to the task of creating a new page, and complicates things when minor changes need to be made.  Don’t you like the clean and streamlined aesthetic of the code sample at the top much better as well?  Plus on some variables like {wrapper_column_open}, which contains:

<!-- Candy comes in a wrapper -->
<
div id="wrapperWit">
    <!--
Hard candy outer shell -->
    <
div id="shell">
        <!--
Gooey center -->
        <
div id="gooey">

The page author doesn’t have to remember any CSS id’s or classes, allowing a designer to control those elements and let the page author focus on content.  In this case, he or she just knows to use {wrapper_column_open} or {wrapper_no_column_open} depending on whether the page needs a column or not.

Yes, embeds help immensely for shared content and markup, but when you do not need tags or PHP, Template Globals are much more efficient, and have a smaller footprint in the template markup itself.  Steve Sharpe had the right idea in his feature article on Jambor-ee about Embeds and Template Globals, but in my mind, still fell a bit short (no offense, Steve, it’s a great article).  In that example, the sample usage for Template Globals doesn’t really show their strengths, but more importantly, the entirety of the header, sidebar, and footer embedded templates in that article could have all lived as Template Globals.

Make wise use of Template Globals and you’ll not only make your site’s development process feel easier (especially in team situations), but you will also benefit from the performance gains of using them instead of embeds wherever appropriate.

I promise Part III will be meatier and have a larger “coolness” factor than this article, but I really felt the need to advocate this feature because so few developers are using it to its full potential.