-
Notifications
You must be signed in to change notification settings - Fork 27
Build your own traditional template engine using Transphporm
Transphporm can be used to build your own mini template system where you do place your logic in the template.
Although this is discouraged, this example shows how flexible Transphporm can be.
The most basic feature a template system needs is a method of replacing content on the page with data. E.g. a marker for displaying the name of the logged in user
With transphporm this would normally be handled by targeting the element that needs replacing. For example:
<header>
<nav>
<ul>
<li><a href="/">Home</a></li>
<li><a href="about/">About</a></li>
<li><a href="contact/">Contact</a></li>
<ul>
<p>Welcome back <a class="accountname" href="profile/">Account Name</a>,
you have <a class="messages" href="/messages">num</a> new messages</p>
</nav>
</header>
layout.html
Transphporm would then replace the account name using
.accountname {
content: data(accountname);
}
.messages {
content: data(messagecount);
}
layout.tss
And it would be compiled using the PHP code
$template = new \Transphporm\Builder('layout.xml', 'layout.tss');
$template->output(['accountname' = > $_SESSION['login'], 'messagecount' => 5]);
This could be expressed using a traditional template engine using code similar to:
<header>
<nav>
<ul>
<li><a href="/">Home</a></li>
<li><a href="about/">About</a></li>
<li><a href="contact/">Contact</a></li>
<ul>
<p>Welcome back <a class="accountname" href="profile/">{{accountname}}</a>,
you have <a class="messages" href="/messages">{{messagecount}}</a> new messages</p>
</nav>
</header>
The template system would then preg_replace
{{accountname}}
and {{messagecount}}
. Although Transphporm cannot do a textual find/replace it can achieve the same thing using elements. Using Transphporm you could create elements which will be replaced.
We'll create the element var and replace it later on:
<header>
<nav>
<ul>
<li><a href="/">Home</a></li>
<li><a href="about/">About</a></li>
<li><a href="contact/">Contact</a></li>
<ul>
<p>Welcome back <a class="accountname" href="profile/"><var data="accountname" /></a>,
you have <a class="messages" href="/messages"><var data="messagecount" /></a> new messages</p>
</nav>
</header>
Then, a generic TSS stylesheet can be applied to every page and used to replace any <var>
element:
var {
content: data(attr(data));
content-mode: replace;
}
n.b. the PHP code that assigns the data would be the same as above
Breaking this down:
var
targets every var
element on the page
attr(data)
reads the contents of the data
attribute for the var
element (in our example, this will either resolve to accountname
or messagecount
).
data(attr(data))
takes the value for the data
attribute and passes it to the data function, this will be equivalent to data(accountname)
or data(messagecount)
which will then be set to the content of the element
content-mode: replace
tells Transphporm to replace the matched <var>
element with the data from the content
attribute, rather than the default behaviour setting the element's content.
Perhaps we only want to display the log in message if the user is logged in, let's add another element called <if>
with the attributes val1
and equals
:
<header>
<nav>
<ul>
<li><a href="/">Home</a></li>
<li><a href="about/">About</a></li>
<li><a href="contact/">Contact</a></li>
<ul>
<if data="loggedin" equals="true">
<p>Welcome back <a class="accountname" href="profile/"><var data="accountname" /></a>,
you have <a class="messages" href="/messages"><var data="messagecount" /></a> new messages</p>
</if>
</nav>
</header>
Then add the TSS to check the condition:
if[equals]:data[attr(data)=attr(equals)] {
content-mode: replace;
content: content();
}
This selector will match any <if>
element where the contents of the data
attribute match the contents of the equals
attribute.
Breaking this down:
if[equals]
selects any if
element with an equals
attribute.
attr(data)
reads the content of the if element's data
attribute.
attr(equals)
reads the content of the if element's equals attribute
:data[attr(data)=attr(equals)]
will resolve to, for example :data[loggedin=true]
content: content()
sets the content of the element to the current content of the element
content-mode: replace
tells transphporm to replace the entire if
block with its contents
notequals could be implemented in a similar way:
if[notequals]:data[attr(data)!=attr(notequals)] {
content-mode: replace;
content: content();
}
And then use the if element with data
and equals
elements.