index.php
:
<?php require_once "PHPTAL/PHPTAL.php"; // name of template. You can set/change it later with setTemplate() $phptal = new PHPTAL("hello.xhtml"); // any field set on PHPTAL object is visible to templates as variable $phptal->who_to_greet = "World"; // execute() returns result of template echo $phptal->execute();
hello.xhtml
:
<p>Hello <em tal:content="who_to_greet"/>!</p>
This is not a requirement, but good advice: avoid passing PHPTAL object (or template abstraction wrapper) around your entire program. MVC programs should be independent of their views (mental exercise: would your application break if there was no view?).
Instead of setting variables directly on PHPTAL object, make your methods return all required information. You can also pass helper objects to PHPTAL which will load data on demand.
<?php $result_array = execute_my_page(); $result_array['logged_in_user'] = find_logged_in_user(); $result_array['sidebar'] = new SidebarHelper(); $phptal = new PHPTAL($page_template); // create PHPTAL object *after* getting data foreach($result_array as $k => $v) $phptal->set($k,$v);
<tal:block>
is an invisible element you can use anywhere. It's useful when you want some TAL functionality, but don't want to litter markup with unnecessary <div>
or <span>
.
METAL macros can be used to execute code from other templates. Conceptually macros are very similar to PHP functions:
function name() {…} | <div metal:define-macro="name">…</div> |
name(); | <div metal:use-macro="name" />
|
function name($argument_name) {…} | <div metal:define-macro="name"> <div metal:define-slot="argument_name"/> </div> |
name("argument data"); | <div metal:use-macro="name"> <div metal:fill-slot="argument_name">argument data</div> </div> |
main.xhtml
:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">\\ <html xmlns="http://www.w3.org/1999/xhtml" metal:define-macro="layout">\\ <head> <title tal:content="title"/> <tal:block metal:define-slot="other-stuff-in-head"/> </head> <body> <div id="main"><tal:block metal:define-slot="maincontent"/></div>\\ </body> </html>
subpage.xhtml
:
<tal:block metal:use-macro="main.xhtml/layout" tal:define="title 'title of the page'"> <p metal:fill-slot="maincontent">Hello world</p> </tal:block>
Note that the code didn't use metal:*-slot
to set title of the page. Macros "see" variables defined in templates that call them, so simple values can be easily passed using variables.
You don't have to fill all slots. Here main.xhtml
defines other-stuff-in-head
slot, which you could use e.g. for adding JavaScript or link to CSS, but you don't have to.