Smarty template Inheritance, include, file templates and template resources in CMS Made Simple

Have you ever tough if there would be more advanced way to build page templates with CMS Made Simple?

Yes there is. I will be going trough few interesting things in this article. You will learn how to include template from CMS Made Simple public template resources, how to include file template, how to work with template inheritance.

teaser.jpg

Template resources:

CMS Made Simple has two interesting public template resources available:

  • template
  • globalcontent

With template resource you can pull any page template and include it to some other page template, or any template in CMS Made Simple. You can also extend (inheritance) to resource templates.

With globalcontent resource you can pull any global content block and pretty much do the same that you can with template resource.

{include}:

Let's start reviewing how {include} works. I have added two global content blocks into system.

First one is called header_html and it looks like this:

{strip}
{content assign='main_content'}
{/strip}
{process_pagedata}<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>

{metadata}
<link rel="shortcut icon" href="favicon.ico" type="image/x-icon">  

<title>{title} - {sitename}</title>

{cms_stylesheet}

</head>
<body>
<div id="main">

    <div id="header">
            
        <div class="logo">
            <img src="gfx/logo.jpg" />
        </div><!-- LOGO END -->
    
        <div id="mainmenu">
            {menu|strip}
        </div><!-- MAINMENU END -->
        
    </div><!-- HEADER END -->
    
    <div id="content">

Second one is called footer_html and it looks like this:

<div class="clearfix"></div>
    </div>
   
</div><!-- MAIN END -->
<div id="footer">
    {global_content name="footer"}
</div><!-- FOOTER END -->
</body>
</html>

Next I created page template that looks like this:

{include file='globalcontent:header_html'}

        <h1>{title}</h1>
        {$main_content}

{include file='info.tpl'}

{include file='globalcontent:footer_html'}

Like you can see I am including template from template resource globalcontent. In general including resource works like: "<resource name>:<resource attribute>". In this case attribute is global content blocks name, with template resource this works exactly same way.

After this I created page where I attached this newly created page template. Output of that page looks like this:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>

<base href="http://10.10.0.12/cms-sandbox/" />
<meta name="Generator" content="CMS Made Simple - Copyright (C) 2004-12 Ted Kulp. All rights reserved." />
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
 

<link rel="shortcut icon" href="favicon.ico" type="image/x-icon">  

<title>include - CMS Made Simple Site</title>

<link rel="stylesheet" type="text/css" href="http://10.10.0.12/cms-sandbox/tmp/cache/stylesheet_combined_4c8c61be4bd3a3fc36d9a112612711ee.css" media="screen" />


</head>
<body>
<div id="main">

    <div id="header">
            
        <div class="logo">
            <img src="gfx/logo.jpg" />
        </div><!-- LOGO END -->
    
        <div id="mainmenu">
             <ul> <li><a href="http://10.10.0.12/cms-sandbox/"><span>main</span></a> </li> <li><a href="http://10.10.0.12/cms-sandbox/index.php?page=2cols"><span>2cols</span></a> </li> <li class="menuactive"><a class="menuactive" href="http://10.10.0.12/cms-sandbox/index.php?page=include"><span>include</span></a> </li> </ul>         </div><!-- MAINMENU END -->
            </div><!-- HEADER END -->         <div id="content">         <h1>include</h1>         Main content         <p> Additional info from $config['root_path']/tmp/templates/info.tpl </p> <div class="clearfix"></div>     </div>     </div><!-- MAIN END --> <div id="footer">     <p>&copy; Copyright 2004-2012 - CMS Made Simple<br /> This site is powered by <a href="http://www.cmsmadesimple.org">CMS Made Simple</a> version 1.11.2</p> </div><!-- FOOTER END --> </body> </html>

Goal with all this is separate header html and footer html, so when you have multiple templates, you don't have to change all templates to modify header or footer code.

In this very same example I am also pulling file template that is located by default in: <CMSMS Root>/tmp/templates. File template works very same way that database template, but from file. You can also include with absolute path, example {include file='/var/www/site/template.tpl'}.

Advantages with this method is that it is simple way doing this, but in the end it's bit ugly and slow.

I still recommend this method over having full templates with minor changes on them. Only consider doing full templates if your whole outfit/layout changes.

Template inheritance:

Template inheritance is part of Smarty 3 engine, it came available in CMS Made Simple 1.11 release.

This is very neat feature, as with inheritance, you can extend to any existent template and replace only parts of it, meaning you can have complete master template and various versions of it with small changes and small amount of code rewritten.

Let's do almost same case I did with include, but with template inheritance.

My master template looks like this:

{strip}
{title assign='title'}
{block name='top'}
    {content assign='main_content'}
{/block}
{/strip}
{process_pagedata}<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>

{metadata}
<link rel="shortcut icon" href="favicon.ico" type="image/x-icon">  

<title>{$title} - {sitename}</title>

{cms_stylesheet}

</head>
<body>
<div id="main">

    <div id="header">
            
        <div class="logo">
            <img src="gfx/logo.jpg" />
        </div><!-- LOGO END -->
    
        <div id="mainmenu">
            {menu|strip}
        </div><!-- MAINMENU END -->
        
    </div><!-- HEADER END -->
    
    <div id="content">
        {block name='content'}
            <h1>{$title}</h1>
            {$main_content}
        {/block}
        <div class="clearfix"></div>
    </div>
    
</div><!-- MAIN END -->

<div id="footer">
    {global_content name="footer"}
</div><!-- FOOTER END -->

</body>
</html>

With {block name='top'} I'm telling template that this part of template can be replaced with block called "top". Inside block I have set default content, witch I would generally use. Block content can also be empty and blocks can be nested.

Let's see how this looks when outputted to pure html:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>


<base href="http://10.10.0.12/cms-sandbox/" />
<meta name="Generator" content="CMS Made Simple - Copyright (C) 2004-12 Ted Kulp. All rights reserved." />
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
 
<link rel="shortcut icon" href="favicon.ico" type="image/x-icon">  

<title>main - CMS Made Simple Site</title>

<link rel="stylesheet" type="text/css" href="http://10.10.0.12/cms-sandbox/tmp/cache/stylesheet_combined_b743c3579819fb5a6dbc19e27b912c9c.css" media="screen" />


</head><body>
<div id="main">

    <div id="header">
            
        <div class="logo">
            <img src="gfx/logo.jpg" />
        </div><!-- LOGO END -->
    
        <div id="mainmenu">
             <ul> <li class="menuactive"><a class="menuactive" href="http://10.10.0.12/cms-sandbox/"><span>main</span></a> </li> <li><a href="http://10.10.0.12/cms-sandbox/index.php?page=2cols"><span>2cols</span></a> </li> <li><a href="http://10.10.0.12/cms-sandbox/index.php?page=include"><span>include</span></a> </li> </ul>         </div><!-- MAINMENU END -->
        
    </div><!-- HEADER END -->
    
    <div id="content">
        
            <h1>main</h1>
            Main content
        
        <div class="clearfix"></div>
    </div>
    
</div><!-- MAIN END -->

<div id="footer">
    <p>&copy; Copyright 2004-2012 - CMS Made Simple<br />
This site is powered by <a href="http://www.cmsmadesimple.org">CMS Made Simple</a> version 1.11.2</p>
</div><!-- FOOTER END -->

</body>
</html>

Next I will be adding another template, let's call it "2cols". In this template I have added second content block and we will be extending this template to master template, and replacing only block parts of it.

Here is how "2cols" template looks like:

{extends file='template:default'}
{block name='top' append}{content block='secondary_content' label='Right' assign='secondary_content'}{/block}
{block name='content'}
        <div id="left">
            <h1>{$title}</h1>
            {$main_content}
        </div>
        
        <div id="right">
            {$secondary_content}
        </div>
{/block}

Instead of having two copies of template with such a small changes I just wrote second template with 12 lines of code.

With first block I am appending data into existing "top" block, not replacing it. With second block called "content" I am rewriting content part of master template.

{extends file='template:default'} tells template that this template extends to resource template "default", witch is name of my master template.

Here is html output of this template:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>

<base href="http://10.10.0.12/cms-sandbox/" />
<meta name="Generator" content="CMS Made Simple - Copyright (C) 2004-12 Ted Kulp. All rights reserved." />
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
 

<link rel="shortcut icon" href="favicon.ico" type="image/x-icon">  

<title>This title is assigned from content - CMS Made Simple Site</title>

<link rel="stylesheet" type="text/css" href="http://10.10.0.12/cms-sandbox/tmp/cache/stylesheet_combined_54aec9ebac013e67f65a4f8f3a3cd999.css" media="screen" />


</head>
<body>
<div id="main">

    <div id="header">
            
        <div class="logo">
            <img src="gfx/logo.jpg" />
        </div><!-- LOGO END -->
    
        <div id="mainmenu">
             <ul> <li><a href="http://10.10.0.12/cms-sandbox/"><span>main</span></a> </li> <li class="menuactive"><a class="menuactive" href="http://10.10.0.12/cms-sandbox/index.php?page=2cols"><span>2cols</span></a> </li> <li><a href="http://10.10.0.12/cms-sandbox/index.php?page=include"><span>include</span></a> </li> </ul>         </div><!-- MAINMENU END -->
        
    </div><!-- HEADER END -->
    
    <div id="content">
        
        <div id="left">
            <h1>This title is assigned from content</h1>
            Main content
        </div>
        
        <div id="right">
            Secondary content
        </div>

        <div class="clearfix"></div>
    </div>
    
</div><!-- MAIN END -->

<div id="footer">
    <p>&copy; Copyright 2004-2012 - CMS Made Simple<br />
This site is powered by <a href="http://www.cmsmadesimple.org">CMS Made Simple</a> version 1.11.2</p>
</div><!-- FOOTER END -->

</body>
</html>

Personally I prefer this method over include method, as it is faster, not just written, but also faster for smarty engine.

I hope this article was educational and useful. If you have further questions, please feel free to add comments or contact me in irc: stikki@irc.freenode.net

Enjoy.

Resources:

http://www.smarty.net/docsv2/en/language.function.include.tpl
http://www.smarty.net/inheritance

Comments