Christoph Studer

mwlib - Template Engine

You are not logged in [Login]

Content

Introduction & overview

mwlib contains a compiling template engine. This means that the template is compiled once to PHP code and thereafter directly executed by the PHP interpreter. As every page/document you see is passed through the template engine it's very important that you know what possibilities you've got.

Keep in mind that the template engine relies on the mwFramework, so I really suggest using the whole mwlib for you projects. Otherwise you'd have to substitute some functionality of the framework with your own implementation.

Ideas & concepts

mwlib templates are more than just "dumb" plain text file where some blocks are replaced by content. mwlib templates contain (part of) the application logic. Many other template engines take a set of input variables and parse them into the document. An mwlib template on the other side defines what modules are loaded and which functions are executed.

So the basic idea is to have the application functionality inside the modules but the application logic inside the templates. Some of you may disagree and may find that kind of "ugly". Because application logic and design should be seperated. Agreed. But I think that it's just not realistic to let a programmer change the PHP code only because a designer decided to have some more information on a page.

A designer may "stick together" an application just by creating a set of templates and linking them. The modules provide functions that can be used in templates to show information. The information could - for example - be a navigation menu. If the designer decides to add another level to the menu hierarchy, he just passes some other parameters to the menu module and adjusts the template. Such changes do not require any line of PHP code.

Compilation

Everytime there is a change in a template, it gets compiled when it's requested the first time after the change. The output (PHP code) is stored in a file in mwlocal/compiled. Therefore, this directory must be writable by the PHP process.

Those files are not made for human eyes, so beware when you look at them ;)

Features


General

  • Compilation to PHP code
  • Easy XML-style-syntax
  • Templates are editable with modern HTML WYSIWYG editors such as Dreamweaver
  • Easy interface at the backend for use in your application/project

Execution

  • Load modules and execute functions
  • Inline PHP code allowed for nasty hacks (maybe removed in further releases!)

Output

  • Repetitive output
  • Conditional output
  • Inclusion of external content
  • Variable transforms
  • Output cache
  • Reporting of unknown variables if needed

Template syntax (for designers)


Basic strucure

mwlib templates are arbitrary plain text documents, the template syntax is in XML style for easy editing in (X)HTML editors.

<template> part

If you want to have some functionality inside your template, just include an XML-Tag called <template> somewhere in your template.

<html>
<template globalvar="somevalue">
    <modules>
        <load name="menu">
             <execute function="menu" someparam="somevalue" otherparam="othervalue"/>
        </load>
    </modules>
</template>
<head><title>My first template</title></head>
<body>
...
</body>
</html>

Everything inside the <template> tag controls the execution and output of the template. For a complete reference, see here.

At compilation time, the <template> part is cut out and compiled to PHP code.

Body

Everything except the <template> part is the body of the template document. There, the output of the module functions can be parsed into the template.

<html>
<template globalvar="somevalue">
    ...
</template>

<head><title>Hello ((user.name))</title></head>
<body>
Hello ((user.name)), it's ((date.time))!
</body>
</html>

See Scalar variables, Conditional output, Repetitive output.

Execution control

This section is on my TODO list.

Loading modules

This section is on my TODO list.

Executing functions

This section is on my TODO list.

Output

Scalar variables ( ((variable)) )

Scalar variables contain the actual information. Their occurrences in the body of the document are simply replaced by their value. To be recognized as variables, they must be enclosed in double brackets.

<html>
<template someglobal="blipp">
  <modules>
    <load name="modulename">
        <execute function="somefunction"/>
    </load>
  </modules>
</template>

<head><title>My template</title></head>
<body>
<p>
  The module 'modulename' would like to output a value: ((modulename.variablename))
</p>
<p>
  There are also global variables such as 'someglobal': ((someglobal))
</p>
</body>
</html>

Scalar variables can be modified/formatted before they are replaced. Read Variable transforms.

Conditional output (<if>)

mwlib templates can hide/show a block of a document depending on a given condition. The condition must contain an output variable. There may optionally be an alternative block that is shown if the condition is not met.

<html>
<template someglobal="blipp">
  <modules>
    <load name="modulename">
        <execute function="somefunction"/>
    </load>
  </modules>
</template>
<head><title>My template</title></head>
<body>
<p>

  <if condition="modulename.ok">
    `modulename.ok' is evaluated as true by PHP
       (may also be a number <> 0 or an array containing at least an element etc.)
  <else/>
    Oh-oh!
  </if>
  <if condition="modulename.someoutput=='somevalue'">
    `modulename.someoutput' has the exact value 'somevalue'
  <else/>
    Oh-oh!
  </if>
  <if condition="modulename.resultcount>5">
    There are more than 5 results.
  <else/>
    Oh-oh!
  </if>
</body>
</html>

Valid comparison operators are: ==, <=, >= and !=. The right hand side is plain PHP code, so use single quotes for strings!

As every output construct, the conditional <if>s may be nested as many time as you like.

Repetitive output (<module.variable>)

The repetitive output is the most interesting construct. It allows you to define a block of a document to be repeated for every instance of a given output item. Inside the block you have all variables of the current (repetition-)instance available for parsing into the document.

<html>
<template someglobal="blipp">
  <modules>
    <load name="modulename">
        <execute function="somefunction"/>
    </load>
  </modules>
</template>
<head><title>My template</title></head>
<body>
<p>

<if condition="modulename.results">
<table>
  <modulename.results>
  <tr>
     <td>((modulename.results.name))</td>
     <td>((modulename.results.email))</td>
     <td>((modulename.results.number))</td>
  </tr>
  </modulename.results>
</table>
<else/>
  <p>No results found.</p>
</if>
</body>
</html>

The table <tr>s are repeated for every item in modulename.results. The variables modulename.results.name, modulename.results.email and modulename.results.number contain the data for the current result item.

As every output construct, the repetitive outputs may be nested as many time as you like. Note that you have to use the full "path" for all variables. So a variable in a 5-fold-nested repetition must be addressed as module.rep1.rep2.rep3.rep4.rep5.variable.

Note that in the example, we first check if there is a result. If not, the whole table is left away and an error message is displayed instead.

I plan to introduce a new addressing abbrevation in later releases of mwlib. The variable that eximplified above would then be module..variable. (".." means: the innermost repetition of the given module.)

Variable transforms

Because modules should be programmed as generic as possible, but templates are client specific, there may be differences in the format that an output variable actually has and the format it should have in the output. For example one must escape some characters if you want to fill a <textarea> HTML control with content.

Therefore, mwlib templates may transform variables with a given rule.

<html>
<template someglobal="blipp">
  <modules>
    <load name="modulename">
        <execute function="somefunction"/>
    </load>
  </modules>
  <transforms>
    <transform variable="modulename.date" rule="mysqlts" format="d.m.Y"/>
  </transforms>
</template>
<head><title>My template</title></head>
<body>
<p>

   The date today is ((modulename.date)).
</body>
</html>

This example converts the variable modulename.date from a MySQL timestamp to a human readable format. The rules and their parameters are defined in the core/mwtransformers.php file.

You may transform a whole set of repetitions by specifying the repetition's name.

I plan to add the possibility to store the result of the transformation in a new variable instead of overwriting the original.

Template API (for developers)

This section is on my TODO list.