Jump to content

Simple tutorial on how to use TemplateFile class


apeisa
 Share

Recommended Posts

I have coded my sites using simple included header & footer technique (similar to how demo site is coded). It has it's merits (simple and straightforward), but on bigger sites it may add lot's of controller logic to header files or a lot of little bit different template files, where logic and markup is mixed.

I know there is TemplateFile class which I assume is something that Ryan uses on most of his projects. Usage looks simple:

<?php

$out = new TemplateFile("./includes/my_markup.html"); 
$out->set('headline', $page->get("headline|title")); 
$out->set('body', $page->body);
$out->set('sidebar', $page->sidebar); 
$out->set('navigation', $pages->find("parent=/"));
echo $out->render();

But how I would code those headline, body etc. variables to my_markup.html file? I assume that my_markup.html can contain php... So are those just $headline, $body, $sidebar etc? Or probably like $this->headline etc?

  • Like 1
Link to comment
Share on other sites

As for how to use the TemplateFile class, you've got it exactly right. You can access everything you set() directly from the var name in the file, such as $headline and $body, etc. If you prefer it, you can also use the setArray() method (inherited from WireData) to do something like this (though I think I prefer the readability of your version):

<?php
echo $out->setArray(array(
    'headline' => $page->get("headline|title"),
    'body' => $page->body,
    'sidebar' => $page->sidebar,
    'navigation' => $pages->find("parent=/")
    ))->render(); 

TemplateFile is  the class that PW uses to output your templates. I actually don't use it very often in my own sites. That's in part because I work mostly alone and don't have to compartmentalize stuff quite as much as if the work was split. I do think it makes sense to use TemplateFile more and more as the size of the team grows and you need templates with limited access and scope (as a good thing). The strategy that I use does not have limited access and scope, but it is probably more efficient and less verbose than using the TemplateFile class. Though it's also a similar approach in many ways too.

The way it works is that all the site templates pull in the same main markup file (main.php). That main markup file is looking for values to be set to the $page object… whether those values were set in PW, or by some other template. Templates may also modify the values (usually appending or prepending) before sending to the main template. If an expected value is not set, then the main template supplies a default. So templates really only need to supply values for those things that they want to change. This is what that main.php markup file might look like:

/site/templates/main.php

<?php

// set default values for topnav and subnav. 
// these aren't PW fields, so we're just using $page to hold values that other templates can override
if(!$page->topnav) $page->topnav = $pages->get("/")->children();
if(!$page->subnav) $page->subnav = $page->children();

// we want all templates to have jquery, main.js and main.css 
$config->scripts->add('jquery.js');
$config->scripts->add('main.js');
$config->styles->add('main.css');

// if a JS or CSS file has the same name as the template, then use it 
if(is_file($config->paths->templates . "scripts/$template.js")) $config->scripts->add("$template.js"); 
if(is_file($config->paths->templates . "styles/$template.css")) $config->styles->add("$template.css"); 

// now output the markup
?>
<!DOCTYPE html> 
<html lang="en"> 
<head>
    <title><?php echo $page->get("browser_title|headline|title"); ?></title>
    <?php 
    foreach($config->scripts as $file) {
        echo "<script src='{$config->urls->templates}scripts/$file'></script>";
    }
    foreach($config->styles as $file) {
        echo "<link rel='stylesheet' type='text/css' href='{$config->urls->templates}styles/$file' />";
    }
    ?>
</head>
<body id='body_<?php echo $page->rootParent->name; /* for targeting in CSS */ ?>'>     

    <div id='topnav'>
        <?php echo $page->topnav->render(); ?>
    </div>

    <div id='subnav'>
        <?php echo $page->subnav->render(); ?>
    </div>

    <div id='bodycopy'>
        <h1><?php echo $page->get('headline|title'); ?></h1>
        <?=$page->body?>
    </div>

    <div id='sidebar'>
        <?=$page->sidebar?>
    </div>

</body>
</html>

Then all the other templates in the site customize the variables that get populated, and they pull in the main template. For instance, the homepage template:

/site/templates/home.php

<?php

// we don't want subnav on homepage, so make it empty
$page->subnav = new PageArray(); 

// list the 3 newest news items in the sidebar
$page->sidebar = "<h2>Latest News</h2>" . $pages->find("parent=/news/, sort=-date, limit=3")->render(); 

// since it's the homepage, we'll add a masthead photo above the body
if($page->photo) {
    $photo = $page->photo->size(600, 200); 
    $page->body = "<img id='masthead_photo' src='{$photo->url}' alt='{$photo->description}' />" . $page->body;
}

// add a note about when it was last updated, just for kicks
$page->body .= "<p>Last updated " . date('m/d/Y H:i:s', $page->modified) . " by {$page->modifiedUser}</p>";

// include the main template
include("./main.php"); 

I also want to mention that main.php isn't actually used directly by any pages... I don't even keep it as a template in PW. Though you certainly could. But I just use main.php for inclusion by other templates.

That's the approach I use most often anyway. What other approaches to people use?

  • Like 2
Link to comment
Share on other sites

Thanks Ryan! I like your method very much. Straightforward and easy to understand. In my experience most sites we build usually go with one or two main templates. One template for frontpage and another for content pages. After that if there is some campaign sites or special subsections then those get their own template if needed (usually css targeting is enough).

(though I think I prefer the readability of your version)

Actually it is also your version, I copied it from another topic where templates are discussed ;)

Link to comment
Share on other sites

  • 2 years later...

Hi there, I know I'm digging out a quite old topic, but I just stumbled across this in the processwire blog profile. 

As the webpages I code right now are often responsive with no real general page layout, exept header and footer part, but lot's of smaller repeated chunks of code (accordions, blocks), I was searching for a simple way of getting templates to work. Plain includes didn't really fit my needs, but a full templating engine seems quite overkill. It's sad that I just now found this class, while I know ProcessWire for over a year now. I think it would be nice to add a paragraph about this in the api section of the page, so it's more visible to new people as a option for generating markup. 

  • Like 1
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...