PHPTAL PHP Template Attribute Language

Prev
PHPTAL Manual ➭ Introduction
Next

Introduction

PHPTAL is an implementation of the excellent Zope Page Template (ZPT) system for PHP. PHPTAL supports TAL, METAL, I18N namespaces.

PHPTALES is the equivalent of TALES, the Template Attribute Language Expression Syntax. It defines how XML attribute values are handled.

As PHPTALES is similar to TALES, it should be easy to port python TAL templates into PHP ones (and vice versa).

To be TAL compliant, PHPTAL implements XPath-like access to data.

PHPTAL is freely distributed under the LGPL license, it is developed by Laurent Bedubourg <lbedubourg@motion-twin.com> and maintained by Kornel Lesiński.

Prev |  | Next
PHPTAL Manual | Home | Why use PHPTAL


Prev
PHPTAL Manual ➭ Why use PHPTAL
Next

Why use PHPTAL

XML/HTML templates exist to separate logic from presentation in web services. This separation brings more than one accompanying benefit.

  • better application design

  • easier task repartition

  • better maintainability

  • easy web skins

Most template systems uses <? ?>, <% %> or <xxx:yyy></xxx:yyy> tags to find their sections. It allows easier template system development but doesn't really help template designers.

TAL hides most of its logic in XML attributes, preserving syntax and strucutre of XHTML. This allows previewing of TAL templates in web browser (WYSIWYG editors, live previews) and doesn't break HTML syntax highlighting in programmers' editors.

If you have already worked with a simple template system, then you must have encountered something looking like:

<table>
  <%loop myarray as myitem %>
  <tr>
    <td><% myitem %></td>
  </tr>
  <%/loop%>
</table>

Well, with PHPTAL you now can write:

<table>
  <tr tal:repeat="myitem myarray">
    <td tal:content="myitem">
      text replaced by the item value
    </td>
    <td tal:replace="">sample 1</td>
    <td tal:replace="">sample 2</td>
    <td tal:replace="">sample 3</td>
  </tr>
</table>

The above code will render correctly with the sample text in normal web browser, so you can present it to your clients even if the code required to get 'myarray' values doesn't yet exist.

Another big advantage of PHPTAL is that you benefit from more than 3 years of Zope community experience, documentation, examples, and help. PHPTAL relies on this community to provide its users a great deal of useful information.

PHPTAL is designed to be as customizable as possible for advanced developers and performance-eating systems, but still be easy to use for beginners, with a comfortable and simple default behaviour (at least we tried :)

Prev |  | Next
Introduction | Home | Installation


Prev
PHPTAL Manual ➭ Installation
Next

Installation

PHPTAL is released as a PEAR package (see pear.php.net). You can download the PHPTAL library on the PHPTAL website: phptal.org.

You can install it using the PEAR utility:

pear install http://phptal.org/latest.tar.gz

Once installed, you can upgrade PHPTAL easily on each PHPTAL update using PEAR:

pear upgrade http://phptal.org/latest.tar.gz

If you do not use PEAR or do not have it installed on your system, you can still install PHPTAL by unzipping the downloaded archive.

tar zxvf PHPTAL-X.X.X.tar.gz
cp -r PHPTAL-X.X.X/PHPTAL* /path/to/your/lib/folder

This will install the PHPTAL.php file and the associated PHPTAL folder in /path/to/your/lib/folder.

Prev |  | Next
Why use PHPTAL | Home | First example


Prev
PHPTAL Manual ➭ First example
Next

First example

To get a first impression of PHPTAL usage, a simple example is better than many words.

Your template is a valid XML/HTML document (with a root element). Here's a file named 'my_template_file.xhtml'.

<?xml version="1.0"?>
<html>
  <head>
    <title tal:content="title">
      Place for the page title
    </title>
  </head>
  <body>
    <h1 tal:content="title">sample title</h1>
    <table>
      <thead>
        <tr>
          <th>Name</th>
          <th>Phone</th>
        </tr>
      </thead>
      <tbody>
        <tr tal:repeat="person people">
          <td tal:content="person/name">person's name</td>
          <td tal:content="person/phone">person's phone</td>
        </tr>
        <tr tal:replace="">
          <td>sample name</td>
          <td>sample phone</td>
        </tr>
        <tr tal:replace="">
          <td>sample name</td>
          <td>sample phone</td>
        </tr>
      </tbody>
    </table>
  </body>
</html>

In PHP, you just have to include the PHPTAL library, and maybe configure a few variables to customize the template system.

<?php
require_once 'PHPTAL.php';

// create a new template object
$template = new PHPTAL('my_template_file.xhtml');

// the Person class
class Person {
    public $name;
    public $phone;

    function Person($name, $phone) {
        $this->name = $name;
        $this->phone = $phone;
    }
}

// let's create an array of objects for test purpose
$people = array();
$people[] = new Person("foo", "01-344-121-021");
$people[] = new Person("bar", "05-999-165-541");
$people[] = new Person("baz", "01-389-321-024");
$people[] = new Person("quz", "05-321-378-654");

// put some data into the template context
$template->title = 'The title value';
$template->people = $people;

// execute the template
try {
    echo $template->execute();
}
catch (Exception $e){
    echo $e;
}
?>

If you execute the PHP script, you will obtain something similar to what follows.

<?xml version="1.0"?>
<html>
  <head>
    <title>The title value</title>
  </head>
  <body>
    <h1>The title value</h1>
    <table>
      <thead>
        <tr>
          <th>Name</th>
          <th>Phone</th>
        </tr>
      </thead>
      <tbody>
        <tr>
          <td>foo</td>
          <td>01-344-121-021</td>
        </tr><tr> <td>bar</td>
          <td>05-999-165-541</td>
        </tr><tr> <td>baz</td>
          <td>01-389-321-024</td>
        </tr><tr> <td>quz</td>
          <td>05-321-378-654</td>
        </tr>
      </tbody>
    </table>
  </body>
</html>

PHPTAL doesn't care much about line breaks and indentation in files it reads and generates. If you want source code of generated HTML files to be pretty (with line breaks and perfect indentation), then you might need to postprocess it with HTML Tidy.

Prev |  | Next
Installation | Home | Template Attribute Language


Prev
PHPTAL Manual ➭ Template Attribute Language
Next

Template Attribute Language

Table of Contents

  1. Attribute priority
  2. TAL namespace
    1. tal:define
    2. tal:condition
    3. tal:repeat
    4. tal:omit-tag
    5. tal:replace
    6. tal:content
    7. tal:attributes
      1. Optional attributes
    8. tal:on-error
  3. METAL namespace
    1. metal:define-macro
    2. metal:use-macro
    3. metal:define-slot
    4. metal:fill-slot
  4. I18N namespace
    1. i18n:translate
    2. i18n:attributes
    3. i18n:name
    4. XHTML in translations
  5. PHPTAL namespace
    1. phptal:debug
    2. phptal:cache
      1. Instant refreshing
      2. Limitations:
    3. phptal:tales
  6. tal:block
  7. PHPTALES
    1. path:
    2. Alternative PHP operator syntax
    3. string:
    4. php:
    5. not:
    6. exists:
    7. default
    8. structure
    9. Expression chains

This section describes TAL and its extensions. It mainly targets template designers but must be read by PHP integrators as well.

Prev |  | Next
First example | Home | Attribute priority


Prev
Template Attribute Language ➭ Attribute priority
Next

Attribute priority

It is important to note that the order of declaration of attributes is irrelevant.

For example,

<span tal:define="usersList application/listUsers"
      tal:condition="somecondition"
      tal:repeat="user usersList"
>…</span>

Is exactly the same as:

<span tal:repeat="user usersList"
      tal:condition="somecondition"
      tal:define="usersList application/listUsers"
>…</span>

Priority is the same as described by the TAL specification:

  1. define

  2. condition

  3. repeat

  4. content or replace

  5. attributes

  6. omit-tag

Prev | Up | Next
Template Attribute Language | Home | TAL namespace


Prev
Template Attribute Language ➭ TAL namespace
Next

TAL namespace

  1. tal:define
  2. tal:condition
  3. tal:repeat
  4. tal:omit-tag
  5. tal:replace
  6. tal:content
  7. tal:attributes
    1. Optional attributes
  8. tal:on-error

URI for this namespace is http://xml.zope.org/namespaces/tal. To use tal: attribute prefix in XML you're required to declare it:

<html xmlns:tal="http://xml.zope.org/namespaces/tal" …>

Note

PHPTAL does not enforce this requirement.

Prev | Up | Next
Attribute priority | Home | tal:define


Prev
Template Attribute Language ➭ TAL namespace ➭ tal:define
Next

tal:define

Defines variables in the template.

It takes one or multiple semicolon-separated variable definitions.

Making a shortcut to a long path:

<div tal:define="destname path/to/existing/variable">…</div>

Defining more than one variable at the same time:

<span tal:define="fname string:Paul; lname string:Dupond">…</span>

Each definition may start with global keyword which makes variable available everywhere later in the template and all macros. Global variables can be redefined.

<span tal:define="global hello string:hello world"/>
<p tal:content="hello"/>

On the contrary, a local variable is only available inside the element it is defined in (and inside marcos that are called in this element):

<span tal:define="hello string:hello world"/>
<p tal:content="hello"/> <!-- will produce an undefined variable error -->

Tip

You may also use tal:define with other attributes, it will be executed before any other attributes on the same element.

Creating a string inside the template:

<span tal:define="destname string:some string" />

Defining a string containing another variable:

<span tal:define="fname string:Paul; hello string:Hello $fname! Welcome to this page" />

A small trick which uses content of the element (useful if you need to define very complex value):

<span tal:define="global hello">Hello ${fname}! Welcome to this page</span>

In above example, the <span> tag won't show up because it has no printable content (hello variable grabs it) nor attributes.

Note

This is a special case. It only works if you use the global keyword.

Prev | Up | Next
TAL namespace | Home | tal:condition


Prev
Template Attribute Language ➭ TAL namespace ➭ tal:condition
Next

tal:condition

The element and its content will be shown only if the condition is evaluated to true.

<p tal:condition="identified"> Welcome member … </p>

<p tal:condition="not: identified">
  Please login before accessing this page
</p>

If the PHP backend does not provide your templates with enough methods, you will often have to fall back to PHP for special conditions:

<span tal:comment="show only if more than five items in the cart"
      tal:condition="php: cart.countItems() GT 5">…</span>

This may put too much logic inside the template and it is sometimes preferable to provide boolean attributes or accessible methods to the template:

<span tal:condition="cart/hasEnoughItems">…</span>

Prev | Up | Next
tal:define | Home | tal:repeat


Prev
Template Attribute Language ➭ TAL namespace ➭ tal:repeat
Next

tal:repeat

This attribute handles iterable objects like arrays, associative arrays, and objects implementing the PHP5 Iterator class.

The repeat attribute repeats its element and its content until the end of the specified resource.

<tr tal:repeat="item some/result">
  <td tal:content="item">text replaced by item</td>
</tr>

Within a loop, you can access the current loop information (and that of its parent for nested loops) using specific repeat/* paths.

In the above example:

  • repeat/item/key : returns the item's key if some/result is an associative resource (index otherwise)

  • repeat/item/index : returns the item index (0 to count-1)

  • repeat/item/number : returns the item number (1 to count)

  • repeat/item/even : returns true if item index is even

  • repeat/item/odd : returns true if item index is odd

  • repeat/item/start : returns true if item is the first one

  • repeat/item/end : returns true if item is the last one

  • repeat/item/length : returns the number of elements in some/result

"item" depends on the receiver variable defined in tal:repeat expression.

The most common usage of tal:repeat is in using some SQL database result. The following code will work if playersRanking contains object that implements PHP's Iterator interface:

<table>
  <thead>
    <tr>
      <th>Position</th>
      <th>Player</th>
      <th>Score</th>
    </tr>
  </thead>
  <tbody>
    <tr tal:repeat="ranking playersRanking">
      <td tal:content="ranking/position"/>
      <td tal:content="ranking/player"/>
      <td tal:content="ranking/score"/>
    </tr>
  </tbody>
</table>

Prev | Up | Next
tal:condition | Home | tal:omit-tag


Prev
Template Attribute Language ➭ TAL namespace ➭ tal:omit-tag
Next

tal:omit-tag

This attribute asks the PHPTAL parser to ignore the elements's open and close tag, its content will still be evaluated.

<span tal:omit-tag="condition">
  if the condition is true, then only this text will appear and span open and close will be removed
</span>

Will produce:

only this text will appear, span open and close will be removed

This attribute is useful when you want to create element optionally, e.g. hide a link if certain condition is met.

If you want element that is never output, you can use tal:block

<tal:block tal:repeat="x php:range(1,10)">only this text will appear, ten times.</tal:block>

Prev | Up | Next
tal:repeat | Home | tal:replace


Prev
Template Attribute Language ➭ TAL namespace ➭ tal:replace
Next

tal:replace

This attribute will replace the entire tag with a value, or by nothing if no value is given.

<span tal:replace="string:this beautiful string">
  this ugly string and span
</span>

Will produce:

this beautiful string

tal:replace can also be used to create samples in source templates, but remove them from final output.

<table>
  <tr tal:repeat="item myresult">
    <td tal:content="item">item value</td>
  </tr>
  <tr tal:replace="">
    <td>sample 1</td>
  </tr>
  <tr tal:replace="">
    <td>sample 2</td>
  </tr>
</table>

Prev | Up | Next
tal:omit-tag | Home | tal:content


Prev
Template Attribute Language ➭ TAL namespace ➭ tal:content
Next

tal:content

This attribute replaces the tag content with the evaluation of its expression.

<span tal:define="myvar string:my string"/>
<span tal:content="myvar">will be replaced</span>

Will produce:

<span>my string</span>

Prev | Up | Next
tal:replace | Home | tal:attributes


Prev
Template Attribute Language ➭ TAL namespace ➭ tal:attributes
Next

tal:attributes

This attribute changes tag attribute(s) value(s).

<a href="http://www.foo.com" title="some foo link"
   tal:attributes="href somelink/href; title somelink/title"
  tal:content="somelink/text"
>sample link</a>

With a 'somelink' having:

$somelink->href = "http://www.google.com";
$somelink->title = "google search engine";
$somelink->text = "the google search engine";

Will produce:

<a href="http://www.google.com"
title="google search engine">the google search engine</a>

Semicolon (;) separates attributes. If you want semicolon to be output in an attribute, you have to double it (;;).

A somewhat complicated example involving tal:repeat:

<tr tal:repeat="ranking playerRankings"
    tal:attributes="class php: repeat.ranking.odd ? 'odd' : NULL">
    …
</tr>

The php: modifier will be explained later, basically if the line is odd then tr will have a class attribute with "odd" as value, otherwise, no class will be set.

The "condition ? then : else" is a regular PHP expression which must be used with care but has proven to be useful on more than one occasion.

A better way to achieve the same result would be to ask your PHP coder to create a custom modifier for your needs (see PHP integration / custom modifiers) which would be used as follows:

<tr tal:repeat="ranking playerRankings"
    tal:attributes="class css-odd:repeat/ranking/odd">
  …
</tr>

The modifier would return "odd" if repeat/ranking/odd is true, NULL otherwise.

Optional attributes

If you use TALES alternatives in tal:attributes and use nothing (or NULL in PHP) as last alternative, attribute won't be added at all if there's no value for it (this avoids adding empty attributes):

… tal:attributes="title object/tooltip | nothing">

XHTML attributes like selected, checked, etc. are properly handled automatically.

<input type="checkbox" tal:attributes="checked object/isChecked"/>

Warning

Remember that XHTML is case-sensitive, so SELECTED attribute is an error in XHTML. Use selected.

Prev | Up | Next
tal:content | Home | tal:on-error


Prev
Template Attribute Language ➭ TAL namespace ➭ tal:on-error
Next

tal:on-error

This attribute replaces the tag by the tal:on-error expression evaluation if a path error is detected in the tag content, or if any PHP exception is thrown in the tag content.

<span tal:on-error="string:No username defined here"
      tal:content="user/name">the user name here</span>

If an error occurs accessing 'name' or 'user', the error string will be shown at the tag's place.

This also works on more than one level of template:

<span tal:on-error="string:error occurred somewhere">
  <span tal:content="user/firstname"/>
  <span tal:content="user/lastname"/>
  <span metal:use-macro="userMenu" />
</span>

Prev | Up | Next
tal:attributes | Home | METAL namespace


Prev
Template Attribute Language ➭ METAL namespace
Next

METAL namespace

  1. metal:define-macro
  2. metal:use-macro
  3. metal:define-slot
  4. metal:fill-slot

URI for this namespace is http://xml.zope.org/namespaces/metal. To use metal: attribute prefix in XML you're required to declare it:

<html xmlns:metal="http://xml.zope.org/namespaces/metal" …>

Note

PHPTAL does not enforce this requirement.

METAL stands for 'Macro Extension for TAL'. This namespace allows template designers to define and call macros. Macros can be used to output data recursively or to include code from other template files.

Prev | Up | Next
tal:on-error | Home | metal:define-macro


Prev
Template Attribute Language ➭ METAL namespace ➭ metal:define-macro
Next

metal:define-macro

This attribute declares a macro. Think of macros as library of small templates which can be reused in any other template.

<div metal:define-macro="main_menu">
  <ul>
    <li><a href="/">home</a></li>
    <li><a href="/products">products</a></li>
    <li><a href="/contact">contact</a></li>
  </ul>

  <div>
    Last modified:
    <span tal:content="mdate">page modification date</span>
  </div>
</div>

Macros inherit all variables from their caller. In the above example, the variable 'mdate' depends on the template that calls the macro.

Prev | Up | Next
METAL namespace | Home | metal:use-macro


Prev
Template Attribute Language ➭ METAL namespace ➭ metal:use-macro
Next

metal:use-macro

This attribute calls a macro and includes its result in the current template.

<span
  tal:comment="main_menu template requires 'mdate' variable"
  tal:define="mdate page/last_modified"
  metal:use-macro="main_menu"
/>

You can refer to external macros defined in other templates by specifying the template source file.

<span metal:use-macro="site_macros.xhtml/main_menu"/>

It is interesting to note that you can also use the PHPTAL inline replacement feature inside the use-macro attribute value:

<span metal:use-macro="${design}/site_macros.xhtml/main_menu"/>

Macro can call itself. This way you can output arrays recursively:

<ul metal:define-macro="show-list">
    <li tal:repeat="item list">
        <tal:block tal:condition="php:is_array(item)" tal:define="list item" metal:use-macro="show-list" />
        <tal:block tal:condition="php:!is_array(item)" tal:content="item" />
    </li>
</ul>

Prev | Up | Next
metal:define-macro | Home | metal:define-slot


Prev
Template Attribute Language ➭ METAL namespace ➭ metal:define-slot
Next

metal:define-slot

This attribute must appear inside a metal:define-macro tag.

Slots can be replaced by caller template with some custom dynamically-generated XML/XHTML.

Slots can be thought of like reverse includes, a macro can be an entire page and slots customize this page depending on the URL. For instance, a slot may contain the latest news in the home page or user actions when the member is logged in.

<span metal:define-slot="news_place">
  <table>
    <tr tal:repeat="item php:latestNews()">
      <td tal:content="item/value">news description</td>
    </tr>
  </table>
</span>

The above example defines a place called 'news_place' which can be overwritten by caller templates. See next section for the continuation of this example.

Prev | Up | Next
metal:use-macro | Home | metal:fill-slot


Prev
Template Attribute Language ➭ METAL namespace ➭ metal:fill-slot
Next

metal:fill-slot

This attribute can occur only inside metal:use-macro element.

This explicitly tells PHPTAL to replace a defined slot with the content provided inside the metal:fill-slot attribute.

<span tal:condition="logged" metal:fill-slot="news_place">
  <h2>user menu</h2>
  <ul>
    <li><a href="/user/action/inbox">inbox</a></li>
    <li><a href="/user/action/new">new mail</a></li>
    <li><a href="/user/action/disconnect">disconnect</a></li>
  </ul>
</span>

Slots give the opportunity to define really customizable and reusable page templates with a simple push technology.

Prev | Up | Next
metal:define-slot | Home | I18N namespace


Prev
Template Attribute Language ➭ I18N namespace
Next

I18N namespace

  1. i18n:translate
  2. i18n:attributes
  3. i18n:name
  4. XHTML in translations

URI for this namespace is http://xml.zope.org/namespaces/i18n. To use i18n: attribute prefix in XML you're required to declare it:

<html xmlns:i18n="http://xml.zope.org/namespaces/i18n" …>

Note

PHPTAL does not enforce this requirement.

Note

i18n is a short name for 'internationalization'. This namespace allow template designers to specify some text zones that must be translated during template evaluation.

Prev | Up | Next
metal:fill-slot | Home | i18n:translate


Prev
Template Attribute Language ➭ I18N namespace ➭ i18n:translate
Next

i18n:translate

This attribute defines some text part that must be translated using PHPTAL's translation system.

<div i18n:translate="string:welcome_message">Welcome here</div>

In the above example, PHPTAL will looks for a translation key named 'welcome_message' and will replace the content of the tag with the equivalent in currently requested language.

<div i18n:translate="">Welcome here</div>

This usage is a little different, no translation key is given, thus PHPTAL will use the content of the tag 'Welcome here' as the translation key. This is a regular translation if translation system knows the key 'Welcome here'.

If no translation is found, the key will be used as the translation result. That's why using readable message instead of keys may be a good choice.

Please note that the key to translate may be contained in a variable, to allow dynamic key selection.

<div tal:define="welcome random_welcome_message">
  <div i18n:translate="welcome">…</div>
</div>
Prev | Up | Next
I18N namespace | Home | i18n:attributes


Prev
Template Attribute Language ➭ I18N namespace ➭ i18n:attributes
Next

i18n:attributes

Defines which attributes should be translated. Takes semicolon-separated list of attributes and keys similar to those for i18n:translate.

<img i18n:attributes="alt 'picture alternative text';title thetitle" alt="Picture" title="${thetitle}" />

Prev | Up | Next
i18n:translate | Home | i18n:name


Prev
Template Attribute Language ➭ I18N namespace ➭ i18n:name
Next

i18n:name

This attribute sets a translation variable value.

Translations may contain ${xxx} strings where "xxx" is the name of a variable that needs to be interpolated dynamically.

The value of this variable will be set to the tag and its content. If you don't need the tag around the value, use tal:replace instead of tal:content. tal:omit-tag may help if the value is a concatenation of strings.

<span i18n:name="myVar" tal:content="some/path"/>
<!-- <span>${some/path}</span> -->

<span i18n:name="myVar" tal:replace="some/path"/>
<!-- ${some/path} -->

<span i18n:name="myVar">foo</span>
<!-- <span>foo</span> -->

<span i18n:name="myVar" tal:omit-tag="">foo</span>
<!-- foo -->

An example of i18n usage:

<div i18n:translate="">
  Welcome <span i18n:name="user" tal:replace="user/name"/>,
  you have <span i18n:name="mails" tal:replace="user/nbrMails"/>
  unread mails.
</div>

The translation key of this example will be:

"Welcome ${user}, you have ${mails} unread mails."

PHPTAL will replace ${user} with ${user/name} and ${mails} with ${user/nbrMails} in translation.

More information about I18N with PHPTAL is available in the PHP section of this book.

Prev | Up | Next
i18n:attributes | Home | XHTML in translations


Prev
Template Attribute Language ➭ I18N namespace ➭ XHTML in translations
Next

XHTML in translations

By defaults translations are assumed to contain only text, so PHPTAL escapes all "<" characters.

You can use structure keyword in i18n:translate to disable escaping and use translated text as-is:

<div i18n:translate="structure '<b>bold text</b>'" />

Gives:

<div><b>bold text</b></div>

Warning

Caveats: This will only work in simplest cases – TAL attributes inside translated strings are ignored. Ill-formed XHTML in translations will break page well-formedness.

Prev | Up | Next
i18n:name | Home | PHPTAL namespace


Prev
Template Attribute Language ➭ PHPTAL namespace
Next

PHPTAL namespace

  1. phptal:debug
  2. phptal:cache
    1. Instant refreshing
    2. Limitations:
  3. phptal:tales

URI for this namespace is http://phptal.org/ns/phptal. To use phptal: attribute prefix in XML you're required to declare it:

<html xmlns:phptal="http://phptal.org/ns/phptal" …>

Note

PHPTAL does not enforce this requirement.

These attributes are not defined in TAL specifications, but are useful when working with PHPTAL.

Prev | Up | Next
XHTML in translations | Home | phptal:debug


Prev
Template Attribute Language ➭ PHPTAL namespace ➭ phptal:debug
Next

phptal:debug

This attribute toggles the activation of PHPTAL debugging for the content of the tag it is defined in.

Note

To debug errors in macros called across templates you need to add phptal:debug in template which defines the macro, not the one which uses it.

The debug mode stores information like filename and source line number in the template, so exceptions thrown by incorrect path access will contain more information about where they where thrown.

<html>
  <head>
    …
  </head>
  <body>
    <div id="menu">
      …
    </div>
    <div id="leftPane" phptal:debug=""
      tal:comment="this div seems buggy, keep
      trace of where errors are thrown">
          …
    </div>
  </body>
</html>

Prev | Up | Next
PHPTAL namespace | Home | phptal:cache


Prev
Template Attribute Language ➭ PHPTAL namespace ➭ phptal:cache
Next

phptal:cache

This attribute causes output of entire element (including its tag) to be cached on disk and not re-evaluated until cache expires.

Note

Use of cache is beneficial only for elements that use very complex expressions, macros from external files or PHP expressions/objects that access the database. Otherwise uncached templates will be just as fast.

Content of this attribute is a duration (how long element should be kept in cache) written as number with 'd', 'h', 'm' or 's' suffix.

<div class="footer" phptal:cache="3h">…</div>

<div> will be evaluated at most once per 3 hours.

Duration can be followed by optional "per" parameter that defines how cache should be shared. By default cache is shared between all pages that use that template. You can add "per url" to have separate copy of given element for every URL.

<ol id="breadcrumbs" phptal:cache="1d per url">…</ol>

<ol> will be cached for one day, separately for each page.

You can add "per expression" to have different cache copy for every different value of an expression (which MUST evaluate to a string).

Note

Expression cannot refer to variables defined using tal:define on the same element.

<ul id="user-info" phptal:cache="25m per object/id">…</ul>

<ul> will be cached for 25 minutes, separately for each object ID.

Warning

Be careful when caching users' private data. Cache will be shared with everyone unless you make it user-specific with per user/id or similar expression.

Instant refreshing

Instead of clearing cache, it might be a better idea to put version or last modification timestamp in the per parameter. This will cause cached template to be refreshed as soon as version/timestamp changes and no special cache clearing will be neccessary.

<div phptal:cache="100d per php:news.id . news.last_modified_date">…</div>

Limitations:

  • phptal:cache blocks can be nested, but outmost block will cache other blocks regardless of their freshness.

  • You cannot use metal:fill-slot inside elements with phptal:cache.

Prev | Up | Next
phptal:debug | Home | phptal:tales


Prev
Template Attribute Language ➭ PHPTAL namespace ➭ phptal:tales
Next

phptal:tales

This attribute allows us to change the behaviour of PHPTALES. The default behaviours is to interpret attribute expressions in a very ZPT way. But sometimes you just would like to have PHP there, and you end up using php: modifier everywhere.

Another problem concerning PHPTALES is the way PHPTAL has to interpret paths. For example, myobject/mymethod/property/10/othermethod/hashkey takes relatively long to interpret (but don't worry about this too much – don't optimize until you find that it is really a problem with performance!)

PHPTAL has (at runtime) to take myobject and discover that it is an object; find out that 'mymethod' is a method of this object (rather than a variable), and then to call it; explore the result to determine that it is an object with a property; find that its value is an array; find the 'ten' element of this array, and determine that it is an object; decide that othermethod is a method of this object (rather than a variable), and get the result of its execution; find that it is an object, and then retrieve the value for the key 'hashkey'.

Of course this was an extreme example and most of the time we don't care, because the process is fast enough. But what if this very long path is called inside a big tal:repeat? D'oh! phptal:tales can help us here:

<html>
  <body>
    <table phptal:tales="php">
      <tr tal:repeat="myobject document.getChildren()">
        <td
          tal:content="myobject.mymethod().property[10].otherMethod().hashkey"></td>
      </tr>
    </table>
  </body>
</html>

Please note that the above example does the same as:

<html>
  <body>
    <table>
      <tr tal:repeat="myobject php:document.getChildren()">
        <td
          tal:content="php:myobject.mymethod().property[10].otherMethod().hashkey"></td>
      </tr>
    </table>
  </body>
</html>

Note

php: modifier is explained in its own chapter.

Prev | Up | Next
phptal:cache | Home | tal:block


Prev
Template Attribute Language ➭ tal:block
Next

tal:block

tal:block is a syntactic sugar for elements which contains many TAL attributes which are not to be echoed.

<tal:block define="myvar string:Some value"/>

is the same as:

<span tal:define="myvar string:Some value" tal:omit-tag=""/>

Another example:

<tal:block condition="someCondition" repeat="item someRepeat">
  <div metal:use-macro="x"/>
</tal:block>

is the same as:

<div tal:omit-tag=""
     tal:condition="someCondition"
     tal:repeat="item someRepeat">
  <div metal:use-macro="x"/>
</div>

Prev | Up | Next
phptal:tales | Home | PHPTALES


Prev
Template Attribute Language ➭ PHPTALES
Next

PHPTALES

  1. path:
  2. Alternative PHP operator syntax
  3. string:
  4. php:
  5. not:
  6. exists:
  7. default
  8. structure
  9. Expression chains

PHPTALES is the equivalent of TALES, the Template Attribute Language Expression Syntax which is the syntax used inside TAL, METAL, PHPTAL attributes and ${…} inline expressions.

In previous examples, you should have seen some PHPTALES examples (string:, php:, not:, …). This chapter describes the usage of PHPTALES in templates.

The value of a TAL attribute may contain more than one expression (ex: tal:define), in which case each expression must be separated from the next one with a ';' character.

Prev | Up | Next
tal:block | Home | path:


Prev
Template Attribute Language ➭ PHPTALES ➭ path:
Next

path:

This is the default modifier used in TAL expression when no other modifier is specified.

The following lines will give the same result:

<span tal:content="data/user/name"/>
<span tal:content="path:data/user/name"/>
<span>${data/user/name}</span>

Inside the template or inside expression strings, you can refer to a context variable using its path in the form ${path/to/my/variable}

<h1>${document/title}</h1>
<span tal:replace="string:welcome ${user/name},
this page has been readed ${page/countRead} times"/>

Warning

If you try to read variable that does not exist, PHPTAL will throw an exception. Use exists: to check if variable can be read

Prev | Up | Next
PHPTALES | Home | Alternative PHP operator syntax


Prev
Template Attribute Language ➭ PHPTALES ➭ Alternative PHP operator syntax
Next

Alternative PHP operator syntax

Because '<', '>' and '&' characters are cumbersome to use in XML, PHPTAL provides alternative syntax for PHP operators using these characters, and a few more for consistency.

These operators can be used only in php: expressions.

  • < : LT (less than)

  • > : GT (greater than)

  • <= : LE (less or equal)

  • >= : GE (greater or equal)

  • == : EQ (equal)

  • != : NE (not equal)

  • && : AND

  • || : OR

Prev | Up | Next
path: | Home | string:


Prev
Template Attribute Language ➭ PHPTALES ➭ string:
Next

string:

Because expressions are separated by a ';' character, and because '$' marks the start of a path, you must use:

  • ';;' when you want to insert a real ';' character in a string,

  • '$$' when you want to insert a real '$' character in a string.

<span tal:replace="string:this is a $$100 page"/>
string:foo $bar baz       <!-- will replace $bar -->
string:foo $$bar baz      <!-- no interpolation -->
string:foo ; php:doFoo()  <!-- two different expressions -->
string:foo ;; php:doFoo() <!-- only string -->

Prev | Up | Next
Alternative PHP operator syntax | Home | php:


Prev
Template Attribute Language ➭ PHPTALES ➭ php:
Next

php:

This expression evaluates what follows as a regular PHP expression except that '->' is replaced by dots '.' and variable names are prefixed with a dollar '$' sign.

A dot '.' separated from the rest of expression by spaces is assumed to be a concatenation sign.

php:htmlentities(foo)
php:'string ${varReplaced}'
php:'string ${some.path().to[0].var}'
php:NOT foo OR (bar GT baz)
php:a + b
php:array('a', 'b', 'c')
php:range(0, 90)
php:foo . a.b.c(e) . htmlentities(SomeClass::staticMethod())
php:SomeClass::ConstOfClass
php:SomeClass::$staticVar

php: should be used with care and won't be needed in 80% of your templates but sometimes you will need to invoke some special PHP method to be certain whether a user is logged in, or to retrieve specific complex data depending on some conditions, dynamically inside the template.

Prev | Up | Next
string: | Home | not:


Prev
Template Attribute Language ➭ PHPTALES ➭ not:
Next

not:

This expression is a boolean one, useful in tal:condition statements.

<span tal:condition="not: logged">not logged</span>

Prev | Up | Next
php: | Home | exists:


Prev
Template Attribute Language ➭ PHPTALES ➭ exists:
Next

exists:

This expression returns true if the path specified after it exists, and false otherwise. It is analogous to PHP's isset().

Normally using a path which doesn't exist throws an error like "Cannot find variable 'foo' in current scope". Thus, uncertain paths must be checked first:

<span tal:condition="exists:user/preferences" tal:content="user/preferences">
  Use user/preferences here if defined
</span>

Tip

In PHPTALES use isset() instead.

Prev | Up | Next
not: | Home | default


Prev
Template Attribute Language ➭ PHPTALES ➭ default
Next

default

This is not an expression but a keyword, allowing template designers to keep the content of a tag as an alternative value if an error occurs, or if something is not defined.

<span tal:define="myVar path/to/possible/var | default">
  default my var value
</span>

<span tal:content="some/var | other/path | default">
  no some/var and no other/path found here
</span>

<a href="unknown.xhtml" title="Unknown page"
   tal:attributes="href item/href | default; title item/title | default"
   tal:content="item/title | default">Unknown page</a>

Above examples introduce the '|' character that allows the definition of alternatives for defines or prints.

Prev | Up | Next
exists: | Home | structure


Prev
Template Attribute Language ➭ PHPTALES ➭ structure
Next

structure

This is not an expression modifier but a keyword.

While printing variables inside PHPTAL templates, you will have noticed that PHPTAL encodes each variable to ensure the validity of the output document.

Sometimes, you may use HTML/XML variables which must be echoed as is.

<h1 tal:content="structure document/title"/>
<span tal:replace="structure document/content"/>

In above examples, we assume that $document->title and $document->content are variables containing preformated HTML which must be echoed as is.

Prev | Up | Next
default | Home | Expression chains


Prev
Template Attribute Language ➭ PHPTALES ➭ Expression chains
Next

Expression chains

An expression chain is a list of expressions separated by '|' characters.

While evaluating expressions separated by '|', PHPTAL will stop its evaluation when an expression value is not null and no error was raised while evaluating the expression.

As a string: expression is always true, string: always terminates an expression chain whatever expression may follow.

You can use php: expressions inside expression chains, like any other expression.

<h1 tal:content="page/title | page/alternativeTitle | php:get_default_title()" />
Prev | Up | Next
structure | Home | PHP Integration


Prev
PHPTAL Manual ➭ PHP Integration
Next

PHP Integration

Table of Contents

  1. Constants
  2. Configuration methods
    1. setOutputMode(mode)
    2. setEncoding(encoding)
    3. Other methods
      1. setTemplateRepository(string_or_array)
      2. setPhpCodeDestination(path)
      3. setPhpCodeExtension(string)
      4. setCacheLifetime(num_days)
      5. setForceReparse(boolean)
  3. class PHPTAL
    1. echoExecute() method
      1. Limitations
  4. interface PHPTAL_Filter
  5. interface PHPTAL_Trigger
  6. interface PHPTAL_TranslationService
    1. method setLanguage(…)
    2. method useDomain($domain)
    3. method setVar($key,$value)
    4. method translate($key)
    5. method setEncoding($encoding)
  7. Working with gettext
    1. Creating the translation directory structure
    2. Portable Object files
    3. Translation Domain
    4. Using Translator in PHP
    5. Variable interpolation
  8. Creating custom expression modifiers

This section is aimed at PHP developers and explains how to use and customize PHPTAL behaviours for simple and advanced usage.

  • PHPTAL: the main PHPTAL class. It is used to load and execute templates.

  • PHPTAL_Filter: filtering template sources and PHPTAL output.

  • PHPTAL_Trigger: handles output of elements with phptal:id.

  • PHPTAL_TranslationService: for replacing the built-in gettext support with your own internationalization system.

Prev |  | Next
Expression chains | Home | Constants


Prev
PHP Integration ➭ Constants
Next

Constants

The only constant defined in PHPTAL.php is PHPTAL_VERSION. It contains version of PHPTAL library installed on your system (in format: X.X.X).

In older versions of there were constants for configuration. They have been removed in favour of methods.

Prev | Up | Next
PHP Integration | Home | Configuration methods


Prev
PHP Integration ➭ Configuration methods
Next

Configuration methods

  1. setOutputMode(mode)
  2. setEncoding(encoding)
  3. Other methods
    1. setTemplateRepository(string_or_array)
    2. setPhpCodeDestination(path)
    3. setPhpCodeExtension(string)
    4. setCacheLifetime(num_days)
    5. setForceReparse(boolean)

PHPTAL tries to use best defaults possible and you shouldn't need to change any of the settings.

All of these are methods of the PHPTAL class. set* methods return instance of their class, so you can chain them:

<?php
  echo $phptal->setPhpCodeDestination('/tmp/phptal')->setOutputMode(PHPTAL::XML)->setTemplate('tpl.zpt')->execute();
?>

is the same as:

<?php
  $phptal->setPhpCodeDestination('/tmp/phptal');
  $phptal->setOutputMode(PHPTAL::XML);
  $phptal->setTemplate('tpl.zpt');
  echo $phptal->execute();
?>

There are other set* methods for filters, internationalisation, etc. They have been described in other sections of this manual.

Prev | Up | Next
Constants | Home | setOutputMode(mode)


Prev
PHP Integration ➭ Configuration methods ➭ setOutputMode(mode)
Next

setOutputMode(mode)

Changes what syntax is used when generating elements. Valid modes are:

PHPTAL::XHTML

In this mode (which is default) PHPTAL will output XHTML in a way that is backwards-compatible with HTML browsers.

  • Empty elements will be forced to use self-closing form (<img/>, <link/>), and non-empty elements will always have closing tag.

    Warning

    XHTML output mode changes <link> element in way that is incompatible with RSS. Use XML output mode to generate RSS feeds or use Atom.

  • Boolean attribtes (checked, selected, etc.) will always have value required by the XHTML specification (it simplifies use of tal:attributes).

  • <![CDATA[ blocks will be added or removed automatically and will use special escaping syntax that is safe in both XML and HTML.

    Tip

    If you're always sending XHTML as application/xhtml+xml, then it's better to use XML output mode.

PHPTAL::HTML5

This mode generates documents that have best compatibility with text/html parsing in current web browsers, but are not XML.

PHPTAL will change DOCTYPEs to <!DOCTYPE html>. Namespace declarations, name prefixes, explicit CDATA sections and other HTML-incompatible constructs will be ommited.

Note

This mode is not a "tag soup". PHPTAL will close all elements properly and quote attributes when it's necesary. Output will be properly formatted HTML 5, and fully backwards-compatible with current HTML 4 browsers.

PHPTAL::XML

This mode outputs "pure" XML without compatibility with text/html parsing. Use this mode when generating feeds, SVG, MathML, RDF and other XML files.

Prev | Up | Next
Configuration methods | Home | setEncoding(encoding)


Prev
PHP Integration ➭ Configuration methods ➭ setEncoding(encoding)
Next

setEncoding(encoding)

Specify charcter encoding used by your templates. The default is UTF-8.

PHPTAL assumes that encoding of all templates and generated documents is the same. BOM (Byte Order Marker) is removed from UTF-8 documents.

Note

PHPTAL does not read encoding from XML files and never converts character encodings.

Tip

Save yourself trouble and always use UTF-8 for everything.

Prev | Up | Next
setOutputMode(mode) | Home | Other methods


Prev
PHP Integration ➭ Configuration methods ➭ Other methods
Next

Other methods

setTemplateRepository(string_or_array)

Specifies where to look for templates. If given a string, it adds it to the list of paths searched. If given array, it replaces the list.

This doesn't mean all your files need to be in the root directory, you can use sub folders to organize your template designer's work. It's just a shortcut which will allow you to reference templates without specifying the real path, but instead their relative path within the repository.

Tip

It's like include_path, but for PHPTAL templates only.

setPhpCodeDestination(path)

To tell PHPTAL where to store its intermediate (temporary) PHP files. By default it uses directory given by PHP's sys_get_tmp_dir(), which usually is '/tmp/' directory.

setPhpCodeExtension(string)

What filename extension should be used for intermediate PHP files. The default is php and frankly, there's no reason to change it.

setCacheLifetime(num_days)

Maximum number of days intermediate files and fragments cached with phptal:cache should be kept.

setForceReparse(boolean)

Forces reparsing of all templates all the time. It should be used only for testing and debugging. It's useful if you're testing prefilters or changing code of PHPTAL itself.

Warning

This slows down PHPTAL very much. Never enable this on production servers!

Prev | Up | Next
setEncoding(encoding) | Home | class PHPTAL


Prev
PHP Integration ➭ class PHPTAL
Next

class PHPTAL

  1. echoExecute() method
    1. Limitations

This is the main library class for you to use.

The most common method of use:

<?php

// include the library
require_once 'PHPTAL.php';

// instantiate a new PHPTAL object using specified template file
$tpl = new PHPTAL('mytemplate.xhtml');

// setting some template context variables
$tpl->title  = 'my title';
$tpl->values = array(1,2,3,4);
$tpl->user   = new User('Joe');

// execute the template and echo the result in a 'secure' way
try {
    echo $tpl->execute();
}
catch (Exception $e){
    echo "Exception thrown while processing template\n";
    echo $e;
}
?>

You can perfectly well choose to specify the template source after setting context variables.

<?php
…
$tpl = new PHPTAL();

// it is a matter of taste but you can use the set() method instead of
// setting context using PHPTAL::__set() like above
$tpl->set('title', 'my title');
$tpl->set('values', array(1,2,3,4));
$tpl->set('user', new User('Joe'));

$tpl->setTemplate('mytemplate.xhtml');
…
?>

You can also decide to use a generated string as the template source instead of using an existing template file:

<?php

$src = <<<EOS
<html>
  <head>
  <title tal:content="title">my title</title>
  </head>
  <body>
    <h1 tal:content="title">my title</h1>
  </body>
</html>
EOS;

require_once 'PHPTAL.php';
$tpl = new PHPTAL();
$tpl->setSource($src);
$tpl->title = 'this is my title';
try {
    echo $tpl->execute();
}
catch (Exception $e){
    echo $e;
}

?>

In the above example, because PHPTAL requires a template source identifier (usually the template file realpath), PHPTAL will use the md5 of the $src parameter as a unique identifier. You may decide to force the identifier using a second setSource() argument:

<?php
$src = <<<EOS
<html>
  <head>
  <title tal:content="title">my title</title>
  </head>
  <body>
    <h1 tal:content="title">my title</h1>
  </body>
</html>
EOS;

require_once 'PHPTAL.php';
$tpl = new PHPTAL();

// If you specify where the source comes from (second argument to setSource),
// PHPTAL will be able to generate more helpful error messages.
$tpl->setSource($src, __FILE__);
$tpl->title = 'this is my title';
try {
    echo $tpl->execute();
}
catch (Exception $e){
    echo $e;
}

?>
Prev | Up | Next
Other methods | Home | echoExecute() method


Prev
PHP Integration ➭ class PHPTAL ➭ echoExecute() method
Next

echoExecute() method

Since most common use of execute() method is to echo its output, PHPTAL offers convenience method that echoes output immedately without buffering. This enables streaming of arbitrarily large output without hitting memory limit.

Note

Fragments of template that use tal:on-error or phptal:cache are buffered regardless.

The code:

<?php
    $tpl = new PHPTAL('template.xhtml');
    $tpl->echoExecute();
?>

is same as:

<?php
    $tpl = new PHPTAL('template.xhtml');
    echo $tpl->execute();
?>

but little faster.

Warning

Currently echoExecute() method has some unexpected limitations.

Limitations

When echoExecute() is used, PHPTAL will throw exception if you call any macro defined in a file that has XML declaration or DOCTYPE.

Typically PHPTAL allows templates to "inherit" DOCTYPE from another file (useful when subpage is calling main layout template), however that is not possible without buffering.

To work around this you can:

  • Keep using echo $tpl->execute() until this limitation is removed.

  • Remove all DOCTYPEs and XML declarations from templates and echo them from PHP before calling echoExecute().

Prev | Up | Next
class PHPTAL | Home | interface PHPTAL_Filter


Prev
PHP Integration ➭ interface PHPTAL_Filter
Next

interface PHPTAL_Filter

This interface allows you to automatically filter templates sources (pre-filters) or PHPTAL result (post-filters).

Pre filters are invoked before the template parsing and won't be invoked until the source template file is modified.

Post filters are invoked after each template execution.

<?php
require_once 'PHPTAL.php';

class MyPreFilter implements PHPTAL_Filter {
    public function filter($source){
        return $source;
    }
}

class MyPostFilter implements PHPTAL_Filter {
    public function filter($xhtml){
        return $xhtml;
    }
}

$tpl = new PHPTAL('mytemplate.xhtml');
$tpl->setPreFilter(new MyPreFilter());
$tpl->setPostFilter(new MyPostFilter());
echo $tpl->execute();
?>

You can set only one pre-Filter and one post-Filter using set*Filter. If you have more than one filter to chain, you can wrap them into a single class, implementing the PHPTAL_Filter interface, which would invoke the filter's chain.

<?php
require_once 'PHPTAL.php';

class FilterChain implements PHPTAL_Filter {
    private $_filters = array();

    public function add(PHPTAL_Filter $filter){
        $this->_filters[] = $filter;
    }

    public function filter($source){
        foreach($this->_filters as $filter){
            $source = $filter->filter($source);
        }
        return $source;
    }
}

$myfilter = new FilterChain();
$myfilter->add(new CommentFilter());  // imaginary filter
$myfilter->add(new TidyFilter());     // imaginary filter

$tpl = new PHPTAL('mytemplate.xhtml');
$tpl->setPostFilter($myFilter);
echo $tpl->execute();
?>
Prev | Up | Next
echoExecute() method | Home | interface PHPTAL_Trigger


Prev
PHP Integration ➭ interface PHPTAL_Trigger
Next

interface PHPTAL_Trigger

The phptal:id attribute was added into the PHPTAL for the PHP5 version to replace the old PHPTAL_Cache interface and to abstract it a little more.

When a phptal:id is reached, PHPTAL will look in its triggers list for a matching id and will invoke the trigger start() and end() methods before entering the element, and just after it.

If the PHPTAL_Trigger::start() method returns PHPTAL_Trigger::SKIPTAG, PHPTAL will ignore the element and its content (start() may echo something to replace it).

If your trigger wants the element and its content to be executed, you'll have to return PHPTAL_Trigger::PROCEED.

The PHPTAL_Trigger::end() will be called after the element (whether it has been executed or not). This allows you to build cache systems using ob_start() in start() and ob_get_contents(), ob_end_clean() in end().

<html>
  …
  <div>
    …
    foo bar baz <span tal:replace="id"/> foo bar baz
    …
  </div>
  …
</html>

For some reason we decide the <div> block requires to be cached. We introduce a phptal:id into the template:

<html>
  …
  <div phptal:id="somePossiblyUniqueKeyword">
    …
    foo bar baz <span tal:replace="id"/> foo bar baz
    …
  </div>
  …
</html>

Then we write our trigger which will cache the <div> content:

<?php
require_once 'PHPTAL.php';
require_once 'PHPTAL/Trigger.php';

class CacheTrigger implements PHPTAL_Trigger
{
    public function start($phptalid, $tpl)
    {
        // this cache depends on 'id' which must appears in
        // the template execution context
        $this->_cachePath = 'cache.' . $tpl->getContext()->id;

        // if already cached, read the cache and tell PHPTAL to
        // ignore the tag content
        if (file_exists($this->_cachePath)){
            $this->_usedCache = true;
            readfile($this->_cachePath);
            return self::SKIPTAG;
        }

        // no cache found, we start an output buffer and tell
        // PHPTAL to proceed (ie: execute the tag content)
        $this->_usedCache = false;
        ob_start();
        return self::PROCEED;
    }

    // Invoked after tag execution
    public function end($phptalid, $tpl)
    {
        // end of tag, if cached file used, do nothing
        if ($this->_usedCache){
            return;
        }

        // otherwise, get the content of the output buffer
        // and write it into the cache file for later usage
        $content = ob_get_contents();
        ob_end_clean();
        echo $content;

        $f = fopen($this->_cachePath, 'w');
        fwrite($f, $content);
        fclose($f);
    }

    private $_cachePath;
    private $_usedCache;
}
?>

The key here is to return from start() with either SKIPTAG or PROCEED.

When SKIPTAG is returned, PHPTAL will just ignore the tag and call end(). This usually means that the trigger takes the hand in deciding what to show there.

When PROCEED is returned, PHPTAL will execute the tag and its content as usual, then call end(). This allows our cache class to play with output buffers to execute the tag once and to store the result in a file which will be used in later calls.

To install our trigger we use:

<?php
require_once 'PHPTAL.php';
require_once 'CacheTrigger.php'; // our custom trigger

$trigger = new CacheTrigger();

$tpl = new PHPTAL('test.xhtml');

// this trigger will only be called for phptal:id="triggerId"
$tpl->addTrigger('somePossiblyUniqueKeyword', $trigger);

$tpl->id = 1;

echo $tpl->execute();

?>

You can add as many triggers as you like to your templates. A generic cache trigger may also handle more than one phptal:id… etc…

Prev | Up | Next
interface PHPTAL_Filter | Home | interface PHPTAL_TranslationService


Prev
PHP Integration ➭ interface PHPTAL_TranslationService
Next

interface PHPTAL_TranslationService

  1. method setLanguage(…)
  2. method useDomain($domain)
  3. method setVar($key,$value)
  4. method translate($key)
  5. method setEncoding($encoding)

PHPTAL comes with a default gettext translation service, as shown in another section. For some reason you may prefer to implement your own service of translation.

The PHPTAL_TranslationService interface is here to serve your needs.

The usage of your service will be the same as the PHPTAL_GetTextTranslator.

$tpl->setTranslator($yourOwnTranslatorInstance);

Your implementation must define the following methods:

Prev | Up | Next
interface PHPTAL_Trigger | Home | method setLanguage(…)


Prev
PHP Integration ➭ interface PHPTAL_TranslationService ➭ method setLanguage(…)
Next

method setLanguage(…)

This method may be called by the template to change the current output language and/or locale (e.g. en_US).

Its arguments are a list of possible languages. Use func_get_args() to get the argument array. The first known language should be used by your service.

Return language that has been set.

<?php
require_once 'PHPTAL/TranslationService.php';

class MyTranslator implements PHPTAL_TranslationService {
…
    public function setLanguage(){
        $langs = func_get_args();
        foreach($langs as $lang){
            // if $lang known use it and stop the loop
            $this->_currentLang = $lang;
            break;
        }
        return $this->_currentLang;
    }
    …
    private $_currentLang;
}
?>
Prev | Up | Next
interface PHPTAL_TranslationService | Home | method useDomain($domain)


Prev
PHP Integration ➭ interface PHPTAL_TranslationService ➭ method useDomain($domain)
Next

method useDomain($domain)

If you decided to store your translations into separate files, one for each application, for example, this method allows you to select the translation domain from your templates (i18n:domain).

<?php
require_once 'PHPTAL/TranslationService.php';

class MyTranslator implements PHPTAL_TranslationService {
    …
    public function useDomain($domain){
        if (!array_key_exists($domain, $this->_domains)){
            $file = "domains/$this->_currentLang/$domain.php";
            $this->_domains[$domain] = include($file);
        }
        $this->_currentDomain = $this->_domains[$domain];
    }
    …
    private $_currentDomain;
    private $_domains = array();
}
?>

The above example is a possible translation solution where keys are stored in PHP files which return an associative array of key => translation.

Prev | Up | Next
method setLanguage(…) | Home | method setVar($key,$value)


Prev
PHP Integration ➭ interface PHPTAL_TranslationService ➭ method setVar($key,$value)
Next

method setVar($key,$value)

This method matches i18n:name calls. It builds an interpolation context for later translate calls.

<?php
require_once 'PHPTAL/TranslationService.php';

class MyTranslator implements PHPTAL_TranslationService {
    …
    public function setVar($key, $value){
        $this->_context[$key] = $value;
    }
    …
    private $_context = array();
}
?>
Prev | Up | Next
method useDomain($domain) | Home | method translate($key)


Prev
PHP Integration ➭ interface PHPTAL_TranslationService ➭ method translate($key)
Next

method translate($key)

The last and most important method to implement, it asks your service to translate the specified key for the currently selected language.

<?php
require_once 'PHPTAL/TranslationService.php';

class MyTranslator implements PHPTAL_TranslationService {
    …
    public function translate($key){
        $value = $this->_currentDomain[$key];

        // interpolate ${myvar} using context associative array
        while (preg_match('/\${(.*?)\}/sm', $value, $m)){
            list($src,$var) = $m;
            if (!array_key_exists($var, $this->_context)){
                $err = sprintf('Interpolation error, var "%s" not set',
                               $var);
                throw new Exception($err);
            }
            $value = str_replace($src, $this->_context[$var], $value);
        }

        return $value;
    }
    …
}
?>
Prev | Up | Next
method setVar($key,$value) | Home | method setEncoding($encoding)


Prev
PHP Integration ➭ interface PHPTAL_TranslationService ➭ method setEncoding($encoding)
Next

method setEncoding($encoding)

PHPTAL class calls this method to inform your translation service what encoding is used by the template. translate() method should return strings in that encoding. If you always use the same encoding for templates and translation files (i.e. UTF-8), you can leave this method empty.

Prev | Up | Next
method translate($key) | Home | Working with gettext


Prev
PHP Integration ➭ Working with gettext
Next

Working with gettext

  1. Creating the translation directory structure
  2. Portable Object files
  3. Translation Domain
  4. Using Translator in PHP
  5. Variable interpolation

gettext is a standard GNU internationalization / translation system which can be used with PHP and which is supported by PHPTAL.

The usage of gettext™ is simple but you will have to perform some tests to be sure everything works fine on your system.

First, PHP must be compiled with the --with-gettext flag. See PHP documentation for how to do this.

You can test your installation using following peace of code:

//
// test if gettext extension is installed with php
//

if (!function_exists("gettext"))
{
    echo "gettext is not installed\n";
}
else
{
    echo "gettext is supported\n";
}

Creating the translation directory structure

The PHP gettext™ extension requires a specific structure which will contain your translation files.

/path/to/your/translation_root/en_US/LC_MESSAGES/
/path/to/your/translation_root/en_GB/LC_MESSAGES/
/path/to/your/translation_root/fr_FR/LC_MESSAGES/
/path/to/your/translation_root/es_ES/LC_MESSAGES/
… and so on …

The language code is composed of two characters defining the language itself (en, fr, es, …) and two characters defining the country (US, GB, FR, ES, …).

The directory pattern is:

<path_to_where_you_want>/<ll_CC>/LC_MESSAGES/

Portable Object files

PO files are plain text files that contain your translation. You can safely edit them by hand.

po minimalistic example (en_US/LC_MESSAGES/mydomain.po):

msgid ""
msgstr ""
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"

msgid "Simple test"
msgstr "A small sentence in english"

Once edited, each PO file must be indexed using:

msgfmt mydomain.po -o mydomain.mo

This command won't work if you don't have gettext™ tools installed on your system.

This will produce a MO file (machine object) indexing your translation for quick access.

Then you have to translate this file in other languages.

po minimalistic example (fr_FR/LC_MESSAGES/mydomain.po):

msgid ""
msgstr ""
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"

msgid "Simple test"
msgstr "Une petite phrase en français"

The translation file must also be indexed:

msgfmt mydomain.po -o mydomain.mo

Translation Domain

The domain is matched against your translation file names. In above examples we used 'mydomain' as domain name.

You can have more than one domain for the same application, it can enhance gettext™'s performance to split your application translations in more than one file.

Using Translator in PHP

<?php
require_once 'PHPTAL.php';
require_once 'PHPTAL/GetTextTranslator.php';

try {
    $tr = new PHPTAL_GetTextTranslator();

    // set language to use for this session (first valid language will
    // be used)
    $tr->setLanguage('en_GB.utf8', 'en_GB');

    // register gettext domain to use
    $tr->addDomain('mydomain', '/path/to/your/translation_root');

    // specify current domain
    $tr->useDomain('mydomain');

    $tpl = new PHPTAL('mytemplate.xhtml');

    // tell PHPTAL to use our translator
    $tpl->setTranslator($tr);

    // output translated template
    echo $tpl->execute();
}
catch (Exception $e){
    echo $e;
}

If you need to translate some other text, that is not in the template (e.g. plaintext e-mail message), you can reuse PHPTAL's translator:

$tr = $tpl->getTranslator();

$subject = $tr->translate("Registration information");

$tr->setVar("user",$username);
$message = $tr->translate("Dear ${user}, thanks for registering!");

mail($email, $subject, $message);

If you're using PHPTAL's standard gettext™ translator, you can use gettext() too.

Variable interpolation

The I18N namespace allows some variable interpolation in your translations.

# english
msgid "welcome"
msgstr "Welcome ${name} you have ${n} mails!"

# french
msgid "welcome"
msgstr "Bienvenue ${name} vous avez recu ${n} messages!"

A template can use this interpolation as follows:

<span i18n:translate="welcome">
  Welcome
  <span i18n:name="name" tal:replace="user/name"/>
  you currently have
  <span i18n:name="n" tal:replace="user/unreadeMails"/>
  unread messages!
</span>

Because i18n:translate contains a value 'welcome', the template data will be ignored and the message given by gettext™ will be used instead.

Prev | Up | Next
method setEncoding($encoding) | Home | Creating custom expression modifiers


Prev
PHP Integration ➭ Creating custom expression modifiers
Next

Creating custom expression modifiers

PHPTAL comes with some basic expression modifiers (not:, exists:, string:, php:, path:).

These modifiers are defined by ZPT specifications but PHPTALES can be extended with your own modifiers to manipulate strings, date, money numbers, objects, whatever…

The aim of a modifier is to return some PHP code that will be included in the template PHP source.

Modifiers are used at parse time. If you change the behaviour of a modifier, you'll have to delete generated PHP files and reparse all templates using it.

Please note that modifiers produce code, and mustn't echo data!

Any PHP function starting with "phptal_tales_" is usuable as a modifier.

Modifiers takes two arguments:

  • $src: the source string after the "modifier:" keyword

  • $nothrow: a boolean which determines whether exceptions may be thrown or not by phptal_path() resolution. This boolean must be propagated whenever you call another phptal_tales_* modifier from within your own modifier.

For example, in the following TAL template,

<span tal:replace="some-modifier: my/path/value"/>

The src argument will be "my/path/value", and the $nothrow boolean will be false, because tal:replace requires the path to be fully resolvable.

An expression like:

<span tal:replace="some-modifier: my/path/value | other/path"/>

Will use 2 modifiers:

  • some-modifier: with "my/path/value" as $src argument and $nothrow set to true because an alternative exists

  • path: with "other/path" as $src, and $nothrow set to false because in case the alternative is not found, tal:replace will be in trouble.

Remember, path: is the implicit modifier used when no other modifier is specified.

Modifiers can use other modifiers to generate simpler PHP code. The example below shows this.

//
// This modifier will return a money formated string (XXX.XX)
//
// usage:
//
//      money: path/to/my/amount
//
// this modifier uses phptal_tales() function to generate the
// PHP code that will return the value of the modifier argument.
//
// in the example:
//
//      money: path/to/my/amount
//
// the produced code will be something looking like:
//
//      sprintf("%01.2f", phptal_path($ctx->path, "to/my/amount"))
//
// This code will be included right into the template where needed.
//
// @param string $src
//      The expression string
// @param string $nothrow
//      A boolean indicating if exceptions may be throw by phptal_path if
//      the path does not exists.
// @return string
//      PHP code to include in the template
//
function phptal_tales_money( $src, $nothrow )
{
    // remove spaces we do not require here
    $src = trim($src);
    return 'sprintf("%01.2f", '.phptal_tales($src, $nothrow).')';
}

Prev | Up | Next
Working with gettext | Home | Appendix A. Note for system administrators


Prev
PHPTAL Manual ➭ Note for system administrators
Next

Appendix A. Note for system administrators

PHPTAL functions by generating PHP files from the template's logic, this means that it needs a directory to store those generated files so they can be parsed by the PHP interpreter.

By default PHPTAL will use the system's temp directory (via PHP's sys_get_temp_dir() function if available) or will try to guess where it should be, /tmp on Unix like systems and c:\windows\temp on Microsoft ones, to store the compiled templates. The default destination can be changed to your liking by calling setPhpCodeDestination() method with the appropriate path. Be it the system's temp directory or a custom one, it needs to have its permissions setup as to allow the PHP running process (the Apache user if using mod_php or the cgi/fastcgi user otherwise) to create and update files in that directory.

PHPTAL creates one file for each different template file and one file for each tag if using phptal:cache. It doesn't create separate files for macros (which are simply compiled as PHP functions inside the compiled template file). These files are automatically cleaned up once in a while, more specifically, each time a template is compiled there is random probability, controlled by setCachePurgeFrequency() method, which will just delete files older than set by setCacheLifetime() method.

Alternatively you can also schedule the deletion of old/unused files by running this from an Unix-like shell (e.g. in a cron job):

find /tmp/ -name tpl_\* \( -atime +1 -o -mtime +14 \) -delete
Prev |  | Next
Creating custom expression modifiers | Home | Appendix B. Useful links


Prev
PHPTAL Manual ➭ Useful links
Next

Appendix B. Useful links

  • ZPT Zope Page Template front page,

  • TAL the Template Attribute Language page,

  • METAL is the Macro Expansion of TAL,

  • TALES the TAL Expression Syntax.

Prev |  | Next
Appendix A. Note for system administrators | Home | Appendix C. Greetings


Prev
PHPTAL Manual ➭ Greetings

Appendix C. Greetings

Big thanks goes to:

  • ZPT team, who made these useful specifications,

  • The PHPTAL community for their support, help and reports,

  • Jean-Michel Hiver, who 'forced' me to look at them,

  • Olivier Parisy, the first enthusiastic PHPTAL user and bug finder,

Prev |
Appendix B. Useful links | Home


PHPTAL :: Mailing list & contact

  • News
  • Introduction
  • Download
  • Manuals
  • FAQ
  • Mailinglist
  • Wiki

Mailing list

Please join the PHPTAL mailing list to report errors, problems and discuss anything related to PHPTAL.

Archives

If you have any problems with PHPTAL, you're likely to find answers in the mailinglist archives.

  • Archives of all discussions
  • Gmane interface

Authors

PHPTAL has been developed by Laurent Bédubourg and currently is maintained by Kornel Lesiński.

PHPTAL is hosted by MotionTwin (Laurent's French company, which develops "fun" gaming/community websites).

Newsfeed | Contact | © 2005-2009 Motion-Twin, Aardvark Media Ltd.


PHPTAL :: Download PHPTAL template engine (tarball, PEAR, SVN)

  • News
  • Introduction
  • Download
  • Manuals
  • FAQ
  • Mailinglist
  • Wiki

Download

The PHPTAL library is licensed under the terms of the GNU Lesser General Public License.

Installation procedure

Manual installation

  1. Download latest tarball or ZIP
  2. Unpack it (e.g. tar zxvf PHPTAL-1.2.0.tar.gz)
  3. Copy files from PHPTAL-1.2.0 directory to anywhere you like (your project or include directory)
  4. Include PHPTAL.php in your scripts (e.g. require_once "my/stuff/libs/phptal/PHPTAL.php";)

PEAR installation

The latest stable release of PHPTAL (1.2.0) is always reachable via latest.tar.gz, and the following will work:

pear install http://phptal.org/latest.tar.gz
pear upgrade http://phptal.org/latest.tar.gz

Source code

You can access latest PHPTAL source code using subversion.

svn co https://svn.motion-twin.com/phptal/trunk phptal

If you are willing to send me patches, please use svn diff to ease the communication.

Of course you can always browse the subversion repository. The trunk folder contains the latest code.

Old versions

You can also install older releases of PHPTAL using specific URLs:

pear install http://phptal.org/files/PHPTAL-1.2.0.tar.gz
pear upgrade http://phptal.org/files/PHPTAL-1.2.0.tar.gz
Newsfeed | Contact | © 2005-2009 Motion-Twin, Aardvark Media Ltd.


PHPTAL :: Frequently Asked Questions about templates

  • News
  • Introduction
  • Download
  • Manuals
  • FAQ
  • Mailinglist
  • Wiki

FAQs and tips

Questions are welcome on the PHPTAL mailing list!

How can I prevent escaping of HTML characters (&amp;, &lt;, &quot;)?

In most cases use structure expression modifier, e.g.:

<p tal:content="structure variable_with_raw_xhtml" />

You should use this only when you're sure that variable contains safe (filtered), well-formed XHTML.

In <script> PHPTAL will change < to &lt;, because this is required by XML. If you're sending XHTML as HTML (using IE-compatible text/html MIME type), then you need to use alternative, HTML-compatible syntax:

<script type="text/javascript">/*<![CDATA[*/
  1 < 2;
  var hello = ${structure php:json_encode("world!");}
/*]]>*/</script>

Note that <![CDATA[ also disables interpretation of TAL tags, so you have to use ${structure expresssion} syntax. It's also a good idea to use json_encode() to convert PHP strings/arrays to JavaScript strings or arrays.

permalink

Output trees recursively (e.g. nested multi-level menus)

Macros work almost like functions and can be used to generate code recursively. Just create macro that calls itself:

<ul metal:define-macro="output_list" tal:condition="list">
    <li tal:repeat="list_item list">
        ${list_item/name}

        <!-- this re-defines list variable
             by assigning the next sub-level of the list to it,
             and then calls this macro again -->
        <tal:block tal:define="list list_item/sublist"
                   metal:use-macro="output_list" />
    </li>
</ul>

<!-- macro definition above isn't automatically run,
     so kick-start the process -->
<tal:block metal:use-macro="output_list" />

The code above will work for structure like this (of course objects could work as well):

<?php
$phptal->list = array(
    array('name'=>'Top level first item', 'sublist'=>array(
        array('name'=>'Second level first item', 'sublist'=>array()),
        array('name'=>'Second level second item', 'sublist'=>array()),
    )),
    array('name'=>'Top level second item', 'sublist'=>array(
        array('name'=>'etc...', 'sublist'=>array(
            array('name'=>'etc...', 'sublist'=>array()),
        )),
    )),
);
?>

permalink

How can I force refresh of phptal:cache? (for example when my news updates)

Manual approach is to tell PHPTAL to delete cached templates:

$phptal = new PHPTAL("templates/news.zpt");
$phptal->cleanUpCache();

A better, fully automatic approach is to put modification date in phptal:cache:

<div phptal:cache="100d per php:news.id . news.last_updated_date">

This means that a separate copy will be cached for every version of every news item. You can use cron to remove outdated copies.

permalink

Interpolation error, var "bla/bla/bla" not set

In translated strings you can't use TALES expressions. Only names defined with i18n:name.

This indirection is there to have simple, clear names in translation keys that your translators won't be confused about and won't break :)

permalink

How can I translate text generated on the fly?

If you've got code like <p tal:content="some_error_message"/> then change it to <p i18n:translate="some_error_message"/>.

Contents of i18n:translate is an expression that evaluates name of translation key at run time.

permalink

How can I translate complex formatted text?

Add structure keyword to the i18n:translate attribute:

<p i18n:translate="structure 'translation-key'">
     <strong>Formatted</strong> text
</p>

And translated text will be used literally, as XHTML code, without escaping (beware that ill-formed XHTML in translations will break your page).

msgid "translation-key"
msgstr "<strong>Formatted</strong> text"

If text contains parts that are dynamic or that you don't want to translate, you can use i18n:name to exclude them. And you can nest i18n:translate:

<p i18n:translate="structure 'translation-key'">
    <strong>Formatted</strong>
    <a href="…" i18n:name="link">
        <tal:block i18n:translate="">link label</tal:block>
    </a>
</p>
msgid "translation-key"
msgstr "<strong>Formatted</strong> ${link}"
msgid "link label"
msgstr "link label"

permalink

How can I add two or more post/pre filters to the template?

Create one wrapper for all your filters:

class MyBunchOfFilters implements PHPTAL_Filter
{
    function filter($code)
    {
        foreach($this->myfilters as $f) $code = $f->filter($code);
        return $code;
    }
}

permalink

Avoid error when variables are undefined

If you don't always pass certain variables to your templates, use exists: expression modifier to ensure variable exists:

<div tal:condition="exists:user">Hello ${user/name}!</div>

Alternatively, you can use | operator and nothing keyword in expressions:

<p>Hello ${user/first_name | 'Anonymous'} ${user/last_name | nothing}</p>

permalink

Newsfeed | Contact | © 2005-2009 Motion-Twin, Aardvark Media Ltd.


PHPTAL :: Template Attribute Language for PHP 5

  • News
  • Introduction
  • Download
  • Manuals
  • FAQ
  • Mailinglist
  • Wiki

PHPTAL is a templating engine for PHP5 that implements brilliant Zope Page Templates syntax:

<div class="item" tal:repeat="item itemsArray">
    <span tal:condition="item/hasDate" tal:replace="item/getDate"/>
    <a href="${item/getUrl}" tal:content="item/getTitle"/>
  <p tal:content="value/getContent"/>
</div>

PHPTAL is fast thanks to compiled templates and fine-grained caching. Makes it easy to generate well-formed XML/XHTML (protected against XSS attacks). PHPTAL's code is mature and improving. Released free under LGPL license.

See the introduction.

News

PHPTAL 1.2.0 released

2009-07-11

Download tarball or ZIP.

Major changes since 1.1.x:

  • PHPTAL's code has been refactored, reorganized, bugfixed, prettified and commented.
  • HTML5 output mode is now available if you need better compatibility with non-XHTML browsers. You can generate both HTML5 and XHTML from same templates just by switching output mode.
  • XML parser improvements: stricter syntax and encoding checks, better handling of namespaces and entities.
  • <![CDATA[ blocks are added automatically where needed for compatibility with text/html and escaping is CDATA-aware.

Changes since alpha:

  • In HTML5 output mode DOCTYPE is automatically changed to <!DOCTYPE html> and namespace declarations/prefixes are omitted.
  • Better support for SimpleXML objects.

Upgrading:

Instructions for alpha version still apply.

To help you find possible incompatibilities and syntax errors there's phptal_lint.sh script. Install PHPTAL 1.2.0 first (PHPTAL.php must be in include_path, or you'll need to modify the script) and then execute:

chmod a+x phptal_lint.sh
./phptal_lint.sh /path/to/your/templates/directory/

You'll get information which templates failed to parse. Please note that this tool is not 100% accurate, because it does not know about your custom modifiers and prefilters. If your templates require these, you'll need to test them yourself.

Fresh website

2009-06-05

New look, bigger text, wider columns, better typography, syntax coloring. Please send complaints/compliments to the mailing list.

PHPTAL has a new home: phptal.org

2009-04-24

A big thanks goes to Levi Stanley from ENE Services LLC who has donated phptal.org domain to the project!

Another PHPTAL 1.2.0 alpha

2009-04-20

Fresh alpha package. Changes since last one:

  • PHPTAL_DIR is gone. PHPTAL now temporarily modifies include_path.

  • DOM-related classes and methods renamed once again.

  • Re-added few basic methods and properties for compatibility with custom attributes written for older PHPTAL versions.

  • GetTextTranslator sets locale's LC_MESSAGES only when LC_ALL doesn't work. This way you don't need full locale installed on the system to use gettext() (you should, however). setLanguage() now returns language that has been set.

  • XML namespace of phptal:* attributes has changed from http://xml.zope.org/namespaces/phptal to http://phptal.org/ns/phptal.

  • &apos; entity is better supported.

  • Lots, lots of code formatting changes and doc comments for conformance with PEAR coding standards.

  • Fixed variable redefinition bug reported by Ciprian Vieru.

  • Fixed parsing of code with class constants and dynamic property names in php: expressions (bug reported by Bobby).

PHPTAL 1.2.0 alpha

2009-03-30

This is alpha release (don't use it on live sites!). It includes long overdue fixes to XML parser and PHPTAL's internals which may require some cosmetic changes to templates. Please test it and report problems and bugs you find.

Upgrading

The biggest difference is in handling of entities. Entities are now unescaped before passing to expressions, i.e. ${php:strlen('&quot;')} “sees” just the quote character and returns 1. In previous versions entities were passed as-is to the expressions (and that example would return 6).

  • Newly added unescaping of entities can expose encoding bugs. Make sure your pages declare document encoding:

    • For XHTML it's best to send Content-Type:application/xhtml+xml;charset=UTF-8 or Content-Type:text/html;charset=UTF-8 HTTP headers (here's how.)
    • Don't use text/xml MIME type, use application/xml instead.
    • In HTML add appropriate <meta> tag or send Content-Type:text/html;charset=UTF-8 HTTP header.

  • If you're not using UTF-8 encoding, you must set encoding you use via $phptal->setEncoding('ISO-8859-…') (or just switch to UTF-8 already! :)

    Only some 8-bit-based encodings are supported. If your encoding is not supported, you may get away with setting ISO-8859-1 instead.

  • All constants except PHPTAL_VERSION have been removed. Remove any PHPTAL-specific define()s and use class methods for configuration (e.g. $phptal->setPhpCodeDestination('/tmp/phptal/') for custom temp directory.)

  • Don't include any PHPTAL's files before including PHPTAL.php.

Improvements

  • Fixed many quirks related to handling of entities in TALES expressions.

  • Fixed escaping in CDATA sections: special characters won't be changed to entities, </ and ]]> will be escaped appropriately for output mode used.

  • Improved XML namespace support. PHPTAL now rejects invalid prefixes and uses namespace URIs internally.

  • Comments are required to be well-formed (-- is not allowed in comments.)

  • HTML5 output mode. There's a bit of controversy around HTML5, so let me be clear: this doesn't allow “tagsoup”. PHPTAL still requires templates to be well-formed XML, and the output aims to be clean and conforming HTML5 text/html syntax.

    HTML5 output mode is optional and enabled by $phptal->setOutputMode(PHPTAL::HTML5). The default output mode is compatible with XHTML/1.x and XHTML5.

  • Ability to add source resolvers. You can easily implement a fake filesystem that e.g. reads templates from the database. This is better than simply using $phptal->setSource(), because it allows external macros to work.

  • Comments starting with <!--! are stripped from output.

  • Better error messages:

    • When document ends prematurely, PHPTAL reports all elements that weren't closed.
    • Exceptions thrown when parsing templates have more accurate file and line (thanks to Wallace McGee for reporting this.)
    • Reworded errors about missing variables in TALES expressions.

  • Small bugs:

    • ${} behaves more like tal:content="".
    • tal:repeat doesn't “leak” variables to outer scope (bug reported by Richard Cernava.)
    • Template cache properly supports change of output mode.

  • Performance improvements:

    • Avoid needless reparsing. If setForceReparse(true) is set, templates are not even saved to disk. Test suite now runs 5-10× faster!
    • Removed redundant includes and require_once. Before and after.
    • Some constants are escaped at compile time.

  • Internal changes:

    • Separated parser from document builder (this will enable custom parsers in the future.)
    • Removed redundant DOM classes.
    • Renamed many DOM classes and methods to use W3C's terminology and be more consistent across PHPTAL's codebase.
    • Much cleaner code for handling of DOM attributes.

Japanese Translation of the Manual

2009-03-02

Tetsuya Mito has kindly provided Japanese translation of the PHPTAL manual.

PHPTAL 1.1.16 Released

2009-02-24

$gotchas--;

  • Now templates are reparsed when prefilters are added/removed (when developing a prefilter, you may still need PHPTAL::setForceReparse() to temporarily disable caching.)
  • No need to include Filter.php before using filters.
  • Calls to non-existent macros fail gracefully with exception, rather than PHP Fatal Error.
  • Fixed bug which caused dynamic macro calls from inside macros that were called from another file, to fail.
  • Added various subclasses of PHPTAL_Exception.

PHPTAL 1.1.15 Released

2009-01-17

This release improves speed and reliability of PHPTAL. Most notably:

  • NULL value of attribute added via tal:attributes now omits entire attribute in most cases (no more class=""!)
  • Iteration via tal:repeat uses Iterator class exactly the same way foreach() (fixes problem reported by Stas Dovgodko)
  • repeat/…/length is read lazily,
  • allow '-' in external and dynamic macro names (bug spotted by Anton),
  • tal:omit-tag executes condition only once,
  • improvements in parsing of ${…} syntax.

Useful resources

2009-01-12

Tomek Pęszor wrote nice tutorial on integration of PHPTAL with the Zend Framework and started repository of PHPTAL filters.

PHPTAL 1.1.14 Released

2008-11-03

This release brings sane handling of non-ASCII characters in gettext translation keys. If you use PHPTAL's i18n features and have non-ASCII characters in translation keys (e.g. your application's native language is other than English), you may need to upgrade your .po files or enable backward compatibility mode (see notes below).

Changes:

  • fixed: non-ASCII characters in translation keys aren't canonicalized by default. setCanonicalize(true) method of PHPTAL_GetTextTranslator enables old behaviour.
  • added: PHPTAL_TranslationService now requires implementation of setEncoding() method. See manual.
  • added: support for structure keyword in i18n:translate, which disables escaping of XML entities, allowing use of XHTML in translation strings.
  • added: objects that implement __call can now throw BadMethodCallException when they don't handle called method, allowing PHPTAL to handle this gracefully.
  • fixed: partially removed support for old tal:define “feature” that caused empty elements to be omitted.
  • fixed: bug in cache purging code caused up-to-date templates to be needlessly reparsed.
  • Improved speed of macro calls across templates.

Upgrade instructions

In 1.1.13 translation key like <p i18n:translate="'żółw'" /> was interpreted as <p i18n:translate="'<C197><C188><C195><C179><C197><C130>w'"> and you had to use msgid "<C197><C188><C195><C179><C197><C130>w" in your .po files.

PHPTAL 1.1.14 stops doing this and keys are now left unchanged. The example above would simply expect msgid "żółw" in the .po file.

If you don't want to change your .po files and want to keep old behaviour, then call setCanonicalize(true) of PHPTAL_GetTextTranslator, e.g.:

$translator = new PHPTAL_GetTextTranslator();
$translator->setLanguage(…);
$translator->setCanonicalize(true); // add this line
$phptal->setTranslator($translator);

To upgrade templates, change <Cxxx> back to bytes. This code snippet will do it:

preg_replace('/<C(\d+)>/e','chr("\1")',$po_file_content)

Download .po upgrade script.

Deutsche Übersetzung des Handbuchs

2008-10-15

Eine von Axel Zöllich betreute, deutsche Übersetzung des Handbuchs ist verfügbar.

  • Der 'Template Attribute Language' Abschnitt ist fertig.
  • Dem Teil 'php Integration' fehlen noch einige Teile.

(Axel Zöllich is working on German translation of the manual!)

PHPTAL presentation

2008-08-20

During August London Web Standards Meetup I gave presentation about PHPTAL.

The presentation is available for download in Apple Keynote and PDF formats.

PHPTAL 1.1.13 released

2008-07-27
  • New template cleanup routines based on patch by Sergio Chersovani and Nicola Aitoro. PHPTAL will now clean up all old template files and will recompile templates also when their timestamp changes to an older one.
  • Added support for PHP constants in TALES.
  • Improved parsing of XML with syntax errors after root node. If you start getting errors about text after root node, wrap your templates in a <tal:block> element.
  • Improved parsing of semicolons in PHP strings, tal:attributes and tal:define.
  • Fixed parsing of backslash escapes in TALES strings (bug reported by Josh Duck)
  • New configuration methods now work properly with external macros (bug reported by Philip Reichenberger)
  • Added workaround for protected __isset/__get (problem reported by Anru Chen)

PHPTAL 1.1.12 released

2008-04-17

New RepeatController by Iván “DrSlump” Montes:

  • based on SPL iterators (to simplify the code),
  • added support for string iteration,
  • added support for letter and roman properties,
  • added support for grouping first and last properties,
  • most properties are computed as needed.

PHPTAL is now easier to use as part of a framework or a plug-in:

  • Required files are included from directory pointed by PHPTAL_DIR constant (it's defined automatically). This makes it easier to use multiple copies of PHPTAL, and eliminates need for include_path.
  • Configuration can be changed without using constants (patch by Werner):
    $t = PHPTAL::create('index.xhtml')
  ->setPhpCodeDestination('application/tmp/')
  ->setPhpCodeExtension('tmp')
  ->setForceReparse(true)
  ->set('title', 'My Title')
  ->set('heading', 'My Heading');

These changes are backwards-compatible: PEAR installations are unaffected, configuration constants are still supported.

PHPTAL 1.1.11 released

2008-01-29

Handy feature, less bugs.

  • nothing or NULL as last alternative in tal:attributes will cause attribute to be omitted entirely,
  • support for systems on which sys_get_temp_dir() does not include trailing slash,
  • fixed warning when clearing cache.

PHPTAL 1.1.10 released

2008-01-26

Hello! My name is Kornel Lesiński and I'm the new maintaner of PHPTAL.

The latest release adds more robust error handling and integrates PHPTAL a bit better with PHP SPL:

  • added support for Countable and ArrayAccess SPL interfaces,
  • added support for superglobals in php: TALES expressions,
  • changed default temp directory to use sys_get_temp_dir() . If this causes trouble, you can override it using define('PHPTAL_PHP_CODE_DESTINATION','/tmp/');
  • added additional safety-checks to code generation and macro execution to prevent invalid templates from triggering PHP errors,
  • fixed small bugs in XML parser,
  • fixed few error messages to be more precise and report proper file/line,
  • changed all exceptions thrown by PHPTAL to inherit PHPTAL_Exception.
pear upgrade http://phptal.org/latest.tar.gz

PHPTAL 1.1.9 released

2007-11-25

Applied patch from Kornel Lesinski

  • Added phptal:cache that caches HTML of any given tag,
  • Added phptal_tale() which returns chained TAL expressions as a single PHP expression. It's equivalent to phptal_tales(), but can be used in more contexts (i.e. ${foo | bar}),
  • metal:fill-block can fill blocks in parent contexts,
  • slightly improved runtime error messages.

Other svn pending fixes:

  • fixed "not" bug with complex php: expressions,
  • fixed tales string backslash escaping,
  • fixed only escape < and > in PCDATA,
  • fixed php:$foo expression which is evaluated to php:${foo} equals $ctx->{$ctx->foo}.

As announced on the mailing like I don't have the time to maintain PHPTAL anymore, Kornel Lesinski kindly proposed himself to take the head of the project and we will plan the hand over during the following weeks. It was a pleasure to give this library to the community!

Thanks to all PHPTAL users, Laurent Bedubourg

pear upgrade http://phptal.org/latest.tar.gz

PHPTAL 1.1.8 released

2006-11-20

Fix and patch release

  • applied tal:repeat patch from Moritz Bechler
  • applied tales registry patch from Moritz Bechler
  • applied memory patch from 'smoking_birds_on_moon'
  • fixed ${structure foo} and ${string:hello world}
  • fixed setTemplate() reset existing prepared template (but not the context)
  • added true: modifier support
  • added structure support to tal:attributes
pear upgrade http://phptal.org/latest.tar.gz

PHPTAL 1.1.5 released

2006-04-09

The 1.1.4 testing is stable and was improved :

  • added: PHPTAL_CommentFilter as a simple and useful demonstration filter
  • added: PHPTAL_PHP_CODE_EXTENSION constant based on William Bailey proposal
  • added: MyClass.myStatic: custom expression modifiers (patch from William Bailey)
  • fixed: ;; bug in string: expressions (patch from William Bailey)
  • some manual documentation concerning local and global keywords

Important: tal:define now fully support global and local take a quick look at the manual for tal:define usage...

pear upgrade http://phptal.org/latest.tar.gz

English manual corrections

2005-12-10

Many thanks to Dan Sheppard.

PHPTAL 1.1.4 (testing) released

2005-12-10

The 1.1 branch has finally been released, here are some changes :

  • added: global local keywords to tal:define
  • fixed: many little errors in the i18n extension
  • fixed: last path in string: not interpolated
  • modif: XHTML empty attributes are now echoed with a value (i.e.: checked="checked")
  • fixed: tal:define and content buffering fixes (patch from William Bailey)
  • fixed: pre filter usage on external macro execution
  • misc: many code refactorings which will lead to a radical library simplification in the future.
pear upgrade http://phptal.org/testing.tar.gz

PHPTAL 1.0.10 latest link fixed

2005-06-08

The latest phptal download link was broken and linked to 1.0.9 release, this is now fixed.

pear upgrade http://phptal.org/latest.tar.gz

PHPTAL 1.0.10

2005-05-22

(bug fix release before 1.1 branch)

  • fixed: echoing an object now calls its __toString() method
  • fixed: false booleans are now echoed as 0 instead of '' (css using item/repeat/odd may require an update)
  • fixed: tal:content, tal:replace and tal:attributes chained expression now ignores null, false and ''
  • fixed: <!-- --> comments were evaluating ${foo}
  • fixed: $${foo} were evaluated inside text nodes
  • fixed: doctype and xml declaration discovery inside deep macro calls
  • fixed: filemtime() warning when using setSource() with no path
pear upgrade http://phptal.org/latest.tar.gz

PHPTAL 1.0.9

2005-04-23
  • when use-macro and define-macro appear in the same tag, slots are shared between macros to allow macro inheritance
  • added PHPTAL::stripComments($bool) which removes xml comments during parsing
  • fixed '0' tag content unexpected behaviour (patch from William Bailey)
  • more tests, minor refactorings and code comments

The next release will include many refactorings which will allow coders to "easily" insert their own namespaces and attributes into PHPTAL.

Pupeno's article (part2) in PHP|Architect

2005-04-22

Pupeno's (Jose Pablo Ezequiel Fernandez Silva) second article was published on the april 2005 issue of php|architect.

This article explains common PHPTALES usage and goes deep into websites internationalisation using PHPTAL and gettext.

PHPTAL 1.0.8

2005-03-30
  • fixed bug with array/0 paths (patch from William Bailey)
  • fixed stupid lt,gt,eq,... replacement in php:'string not gt foo'

PHPTAL 1.0.7

2005-03-29
  • added template string execution PHPTAL::setSource($src, $path=false)
  • fixed tal:attributes and zero values error
  • latest release is now reachable at http://phptal.org/latest.tar.gz

PHPTAL manual v1 released

2005-03-27

The new PHPTAL for PHP5 manual is available. Corrections, remarks and translations are welcome (join the mailing list).

Pupeno's article in PHP|Architect

2005-03-22

Pupeno's (Jose Pablo Ezequiel Fernandez Silva) first article about PHPTAL was published on the issue 3, volume 4 of php|architect.

This article introduces PHPTAL and explains most common TAL attributes with some good examples.

More articles should follow in next issues concerning advanced PHPTAL usage in daily applications.

Newsfeed | Contact | © 2005-2009 Motion-Twin, Aardvark Media Ltd.


PHPTAL :: Introduction

  • News
  • Introduction
  • Download
  • Manuals
  • FAQ
  • Mailinglist
  • Wiki

Introduction

PHPTAL is a PHP implementation of ZPT work. To be short, PHPTAL is a XML/XHTML template library for PHP.

While most web developpers continue to use ASP/JSP/PHP tags as the core language of their templates, the Zope community came with a refreshing idea named TAL. The idea was to move presentation actions inside XHTML attributes instead of using plain tags or elements.

Let's start with a simple PHP exemple (usually reproduceable in ASP/JSP):

<?php foreach ($values as $value): ?>
<div class="item">
  <div class="title">
    <?php if ($value->hasDate()): ?><?=$value->getDate()?><?php endif; ?>
    <a href="<?= $value->getUrl() ?>"><?=
        htmlentities($value->getTitle())
    ?></a>
  </div>
  <div class="content">
    <?= htmlentities($value->getContent()) ?>
  </div>
</div>
<?php endforeach; ?>

Let's have a look at the TAL way:

<div class="item" tal:repeat="value values">
  <div class="title">
    <span tal:condition="value/hasDate" tal:replace="value/getDate"/>
    <a tal:attributes="href value/getUrl" tal:content="value/getTitle"/>
  </div>
  <div id="content" tal:content="value/getContent"/>
</div>

Now it's up to you to choose which version you prefer. Of course those tal:condition, tal:replace and tal:repeat may looks strange when begining with TAL.

Just for fun let's modify this example:

<div class="item" tal:repeat="value values">
  <div class="title">
    <span tal:condition="value/hasDate" tal:replace="value/getDate">
      2008-10-06
    </span>
    <a href="sample.html"
      tal:attributes="href value/getUrl"
      tal:content="value/getTitle">
      My item title
    </a>
  </div>
  <div class="content" tal:content="value/getContent">
    This is a sample content which is replaced by the
    real content when the template is run with real
    data.
  </div>
</div>

More in the manual.

Some PHPTAL advantages and features:

  • enforces the separation between logic and presentation (the holy grail),
  • warns you if you forget to close an HTML tag or have syntax errors in your template,
  • no more htmlentities(),
  • quite clean and readable templates,
  • ability to insert sample text inside template to preview template result without PHP backend,
  • integrates quite well with WYSIWYG HTML editors,
  • data abstraction using XPath-like system,
  • cool HTML macro system,
  • integrated internationalization system (using gettext or your own backend),
  • ability to replace XPath-like system with PHP expressions,
  • nearly no speed loss (templates are compiled, expensive expressions can be replaced with plain PHP).
  • compatible with PHP accelerators, which can improve performance even further,
  • more than four years of ZPT community support (see zope website),
  • extensible and easily hackable code,
  • makes good use of PHP5 and SPL.

Some PHPTAL drawbacks:

  • a dependency for your application,
  • some TAL, METAL, I18N and PHPTAL attributes to understand,
  • you'll have to produce clean XHTML.
Newsfeed | Contact | © 2005-2009 Motion-Twin, Aardvark Media Ltd.


PHPTAL :: Manual/Tutorial

  • News
  • Introduction
  • Download
  • Manuals
  • FAQ
  • Mailinglist
  • Wiki

Manuals

Questions are welcome on PHPTAL mailing list!

In English

  • HTML — one page per chapter
  • HTML — one big page
  • Plain text

Other resources

  • Integration with PHP frameworks
  • Zope Page Templates Reference written for the original TAL.

In German

Please send corrections and suggestions to Axel Zöllich.

  • HTML — one page per chapter
  • HTML — one big page
  • Plain text

In Russian

Translation isn't finished yet.

  • HTML — one page per chapter
  • HTML — one big page
  • Plain text

In Polish

  • Na stronie phptal.bukox.pl

In Japanese

  • HTML — one big page
Newsfeed | Contact | © 2005-2009 Motion-Twin, Aardvark Media Ltd.


PHPTAL :: Template Attribute Language for PHP 5

  • News
  • Introduction
  • Download
  • Manuals
  • FAQ
  • Mailinglist

Page not found

Sorry, couldn't find “PHPTAL-includes-1.1.svg” on this server.

Newsfeed | Contact | © 2005-2009 Motion-Twin, Aardvark Media Ltd.


PHPTAL :: Template Attribute Language for PHP 5

  • News
  • Introduction
  • Download
  • Manuals
  • FAQ
  • Mailinglist

Page not found

Sorry, couldn't find “PHPTAL-includes-1.2.svg” on this server.

Newsfeed | Contact | © 2005-2009 Motion-Twin, Aardvark Media Ltd.


<?php
if (!isset($_SERVER['argv']) || count($_SERVER['argv']) < 2) die("Converts PHPTAL 1.1.13 .po files to 1.1.14.\n\nRun from CLI with filenames as arguments.\n");

$ok = false;
foreach(array_slice($_SERVER['argv'],1) as $filename)
{
    $text = @file_get_contents($filename);
    if ($text === false) {fprintf(STDERR,"Can't load file $filename.\n");continue;}

    $newtext = preg_replace('/<C(\d+)>/e','chr("\1")',$text);

    if ($newtext !== $text)
    {
        if (false === file_put_contents($filename,$newtext)) {fprintf(STDERR,"Can't load file $filename.\n");continue;}
        $ok = true;
        echo "File $filename converted.\n";
    }
    else
    {
        echo "File $filename did not need updating.\n";
    }
}

exit(!$ok);


PHPTAL :: files

If this page is not well rendered by your browser, upgrade your browser or replace it.

PHPTAL-1.0.0.tar.gz

2009-05-28 16:37:37 37.52 Ko

PHPTAL-1.0.1.tar.gz

2009-05-28 16:37:37 37.55 Ko

PHPTAL-1.0.10.tar.gz

2009-05-28 16:37:37 45.03 Ko

PHPTAL-1.0.11.tar.gz

2009-05-28 16:37:37 44.63 Ko

PHPTAL-1.0.2.tar.gz

2009-05-28 16:37:37 39.61 Ko

PHPTAL-1.0.3.tar.gz

2009-05-28 16:37:37 38.60 Ko

PHPTAL-1.0.4.tar.gz

2009-05-28 16:37:37 40.11 Ko

PHPTAL-1.0.5.tar.gz

2009-05-28 16:37:37 38.92 Ko

PHPTAL-1.0.6.tar.gz

2009-05-28 16:37:37 39.35 Ko

PHPTAL-1.0.7.tar.gz

2009-05-28 16:37:37 39.82 Ko

PHPTAL-1.0.8.tar.gz

2009-05-28 16:37:37 39.77 Ko

PHPTAL-1.0.9.tar.gz

2009-05-28 16:37:37 45.18 Ko

PHPTAL-1.1.10.tar.gz

2009-05-28 16:37:37 51.31 Ko

PHPTAL-1.1.11.tar.gz

2009-05-28 16:37:37 50.72 Ko

PHPTAL-1.1.12.tar.gz

2009-05-28 16:37:37 53.90 Ko

PHPTAL-1.1.13.tar.gz

2009-05-28 16:37:37 55.26 Ko

PHPTAL-1.1.14.tar.gz

2009-05-28 16:37:37 56.13 Ko

PHPTAL-1.1.15.tar.gz

2009-05-28 16:37:37 56.75 Ko

PHPTAL-1.1.16.tar.gz

2009-05-28 16:37:37 57.28 Ko

PHPTAL-1.1.5.tar.gz

2009-05-28 16:37:37 48.66 Ko

PHPTAL-1.1.6.tar.gz

2009-05-28 16:37:37 49.71 Ko

PHPTAL-1.1.7.tar.gz

2009-05-28 16:37:37 49.71 Ko

PHPTAL-1.1.8.tar.gz

2009-05-28 16:37:37 48.47 Ko

PHPTAL-1.1.9.tar.gz

2009-05-28 16:37:37 50.24 Ko

PHPTAL-1.2.0.tar.gz

2009-07-11 03:08:51 67.29 Ko

PHPTAL-1.2.0.zip

2009-07-11 03:04:51 104.38 Ko

PHPTAL-1.2.0a1.tar.gz

2009-05-28 16:37:37 58.91 Ko

PHPTAL-1.2.0a2.tar.gz

2009-05-28 16:37:37 58.57 Ko

PHPTAL-1.2.0a3.tar.gz

2009-05-28 16:37:37 59.02 Ko

PHPTAL-1.2.0a4.tar.gz

2009-05-28 16:37:37 59.83 Ko

PHPTAL-1.2.0a5.tar.gz

2009-05-28 16:37:37 61.44 Ko

PHPTAL-1.2.0a7.tar.gz

2009-05-28 16:37:37 62.78 Ko

PHPTAL-1.2.0a8.tar.gz

2009-05-28 16:37:37 81.92 Ko

PHPTAL-1.2.0a9.tar.gz

2009-05-28 16:37:37 81.87 Ko

PHPTAL-1.2.0alpha10.tar.gz

2009-05-28 16:37:37 117.25 Ko

PHPTAL-1.2.0alpha11.tar.gz

2009-05-28 16:37:37 118.08 Ko

PHPTAL-1.2.0alpha12.tar.gz

2009-05-28 16:37:37 118.39 Ko

PHPTAL-1.2.0beta1.tar.gz

2009-05-28 16:37:37 119.42 Ko

PHPTAL-1.2.0beta3.tar.gz

2009-05-28 16:37:37 138.81 Ko

PHPTAL-1.2.0beta4.tar.gz

2009-06-08 18:07:06 140.49 Ko

PHPTAL-1.2.1b1.tar.gz

2009-09-01 13:40:57 139.52 Ko

PHPTAL-1.2.1b3.tar.gz

2009-09-16 01:19:27 144.63 Ko

phptal_lint.sh

2009-07-11 02:23:46 4.71 Ko


PHPTAL Manual

PHP Template Attribute Language

Laurent Bédubourg

Kornel Lesiński

Dan Sheppard

Anton Valeriyevich Andriyevskyy

Revision History

Table of Contents

  1. Introduction
  2. Why use PHPTAL
  3. Installation
  4. First example
  5. Template Attribute Language
    1. Attribute priority
    2. TAL namespace
      1. tal:define
      2. tal:condition
      3. tal:repeat
      4. tal:omit-tag
      5. tal:replace
      6. tal:content
      7. tal:attributes
        1. Optional attributes
      8. tal:on-error
    3. METAL namespace
      1. metal:define-macro
      2. metal:use-macro
      3. metal:define-slot
      4. metal:fill-slot
    4. I18N namespace
      1. i18n:translate
      2. i18n:attributes
      3. i18n:name
      4. XHTML in translations
    5. PHPTAL namespace
      1. phptal:debug
      2. phptal:cache
        1. Instant refreshing
        2. Limitations:
      3. phptal:tales
    6. tal:block
    7. PHPTALES
      1. path:
      2. Alternative PHP operator syntax
      3. string:
      4. php:
      5. not:
      6. exists:
      7. default
      8. structure
      9. Expression chains
  6. PHP Integration
    1. Constants
    2. Configuration methods
      1. setOutputMode(mode)
      2. setEncoding(encoding)
      3. Other methods
        1. setTemplateRepository(string_or_array)
        2. setPhpCodeDestination(path)
        3. setPhpCodeExtension(string)
        4. setCacheLifetime(num_days)
        5. setForceReparse(boolean)
    3. class PHPTAL
      1. echoExecute() method
        1. Limitations
    4. interface PHPTAL_Filter
    5. interface PHPTAL_Trigger
    6. interface PHPTAL_TranslationService
      1. method setLanguage(…)
      2. method useDomain($domain)
      3. method setVar($key,$value)
      4. method translate($key)
      5. method setEncoding($encoding)
    7. Working with gettext
      1. Creating the translation directory structure
      2. Portable Object files
      3. Translation Domain
      4. Using Translator in PHP
      5. Variable interpolation
    8. Creating custom expression modifiers
  7. A. Note for system administrators
  8. B. Useful links
  9. C. Greetings

Introduction

PHPTAL is an implementation of the excellent Zope Page Template (ZPT) system for PHP. PHPTAL supports TAL, METAL, I18N namespaces.

PHPTALES is the equivalent of TALES, the Template Attribute Language Expression Syntax. It defines how XML attribute values are handled.

As PHPTALES is similar to TALES, it should be easy to port python TAL templates into PHP ones (and vice versa).

To be TAL compliant, PHPTAL implements XPath-like access to data.

PHPTAL is freely distributed under the LGPL license, it is developed by Laurent Bedubourg <lbedubourg@motion-twin.com> and maintained by Kornel Lesiński.

Why use PHPTAL

XML/HTML templates exist to separate logic from presentation in web services. This separation brings more than one accompanying benefit.

  • better application design

  • easier task repartition

  • better maintainability

  • easy web skins

Most template systems uses <? ?>, <% %> or <xxx:yyy></xxx:yyy> tags to find their sections. It allows easier template system development but doesn't really help template designers.

TAL hides most of its logic in XML attributes, preserving syntax and strucutre of XHTML. This allows previewing of TAL templates in web browser (WYSIWYG editors, live previews) and doesn't break HTML syntax highlighting in programmers' editors.

If you have already worked with a simple template system, then you must have encountered something looking like:

<table>
  <%loop myarray as myitem %>
  <tr>
    <td><% myitem %></td>
  </tr>
  <%/loop%>
</table>

Well, with PHPTAL you now can write:

<table>
  <tr tal:repeat="myitem myarray">
    <td tal:content="myitem">
      text replaced by the item value
    </td>
    <td tal:replace="">sample 1</td>
    <td tal:replace="">sample 2</td>
    <td tal:replace="">sample 3</td>
  </tr>
</table>

The above code will render correctly with the sample text in normal web browser, so you can present it to your clients even if the code required to get 'myarray' values doesn't yet exist.

Another big advantage of PHPTAL is that you benefit from more than 3 years of Zope community experience, documentation, examples, and help. PHPTAL relies on this community to provide its users a great deal of useful information.

PHPTAL is designed to be as customizable as possible for advanced developers and performance-eating systems, but still be easy to use for beginners, with a comfortable and simple default behaviour (at least we tried :)

Installation

PHPTAL is released as a PEAR package (see pear.php.net). You can download the PHPTAL library on the PHPTAL website: phptal.org.

You can install it using the PEAR utility:

pear install http://phptal.org/latest.tar.gz

Once installed, you can upgrade PHPTAL easily on each PHPTAL update using PEAR:

pear upgrade http://phptal.org/latest.tar.gz

If you do not use PEAR or do not have it installed on your system, you can still install PHPTAL by unzipping the downloaded archive.

tar zxvf PHPTAL-X.X.X.tar.gz
cp -r PHPTAL-X.X.X/PHPTAL* /path/to/your/lib/folder

This will install the PHPTAL.php file and the associated PHPTAL folder in /path/to/your/lib/folder.

First example

To get a first impression of PHPTAL usage, a simple example is better than many words.

Your template is a valid XML/HTML document (with a root element). Here's a file named 'my_template_file.xhtml'.

<?xml version="1.0"?>
<html>
  <head>
    <title tal:content="title">
      Place for the page title
    </title>
  </head>
  <body>
    <h1 tal:content="title">sample title</h1>
    <table>
      <thead>
        <tr>
          <th>Name</th>
          <th>Phone</th>
        </tr>
      </thead>
      <tbody>
        <tr tal:repeat="person people">
          <td tal:content="person/name">person's name</td>
          <td tal:content="person/phone">person's phone</td>
        </tr>
        <tr tal:replace="">
          <td>sample name</td>
          <td>sample phone</td>
        </tr>
        <tr tal:replace="">
          <td>sample name</td>
          <td>sample phone</td>
        </tr>
      </tbody>
    </table>
  </body>
</html>

In PHP, you just have to include the PHPTAL library, and maybe configure a few variables to customize the template system.

<?php
require_once 'PHPTAL.php';

// create a new template object
$template = new PHPTAL('my_template_file.xhtml');

// the Person class
class Person {
    public $name;
    public $phone;

    function Person($name, $phone) {
        $this->name = $name;
        $this->phone = $phone;
    }
}

// let's create an array of objects for test purpose
$people = array();
$people[] = new Person("foo", "01-344-121-021");
$people[] = new Person("bar", "05-999-165-541");
$people[] = new Person("baz", "01-389-321-024");
$people[] = new Person("quz", "05-321-378-654");

// put some data into the template context
$template->title = 'The title value';
$template->people = $people;

// execute the template
try {
    echo $template->execute();
}
catch (Exception $e){
    echo $e;
}
?>

If you execute the PHP script, you will obtain something similar to what follows.

<?xml version="1.0"?>
<html>
  <head>
    <title>The title value</title>
  </head>
  <body>
    <h1>The title value</h1>
    <table>
      <thead>
        <tr>
          <th>Name</th>
          <th>Phone</th>
        </tr>
      </thead>
      <tbody>
        <tr>
          <td>foo</td>
          <td>01-344-121-021</td>
        </tr><tr> <td>bar</td>
          <td>05-999-165-541</td>
        </tr><tr> <td>baz</td>
          <td>01-389-321-024</td>
        </tr><tr> <td>quz</td>
          <td>05-321-378-654</td>
        </tr>
      </tbody>
    </table>
  </body>
</html>

PHPTAL doesn't care much about line breaks and indentation in files it reads and generates. If you want source code of generated HTML files to be pretty (with line breaks and perfect indentation), then you might need to postprocess it with HTML Tidy.

Template Attribute Language

Table of Contents

  1. Attribute priority
  2. TAL namespace
    1. tal:define
    2. tal:condition
    3. tal:repeat
    4. tal:omit-tag
    5. tal:replace
    6. tal:content
    7. tal:attributes
      1. Optional attributes
    8. tal:on-error
  3. METAL namespace
    1. metal:define-macro
    2. metal:use-macro
    3. metal:define-slot
    4. metal:fill-slot
  4. I18N namespace
    1. i18n:translate
    2. i18n:attributes
    3. i18n:name
    4. XHTML in translations
  5. PHPTAL namespace
    1. phptal:debug
    2. phptal:cache
      1. Instant refreshing
      2. Limitations:
    3. phptal:tales
  6. tal:block
  7. PHPTALES
    1. path:
    2. Alternative PHP operator syntax
    3. string:
    4. php:
    5. not:
    6. exists:
    7. default
    8. structure
    9. Expression chains

This section describes TAL and its extensions. It mainly targets template designers but must be read by PHP integrators as well.

Attribute priority

It is important to note that the order of declaration of attributes is irrelevant.

For example,

<span tal:define="usersList application/listUsers"
      tal:condition="somecondition"
      tal:repeat="user usersList"
>…</span>

Is exactly the same as:

<span tal:repeat="user usersList"
      tal:condition="somecondition"
      tal:define="usersList application/listUsers"
>…</span>

Priority is the same as described by the TAL specification:

  1. define

  2. condition

  3. repeat

  4. content or replace

  5. attributes

  6. omit-tag

TAL namespace

  1. tal:define
  2. tal:condition
  3. tal:repeat
  4. tal:omit-tag
  5. tal:replace
  6. tal:content
  7. tal:attributes
    1. Optional attributes
  8. tal:on-error

URI for this namespace is http://xml.zope.org/namespaces/tal. To use tal: attribute prefix in XML you're required to declare it:

<html xmlns:tal="http://xml.zope.org/namespaces/tal" …>

Note

PHPTAL does not enforce this requirement.

tal:define

Defines variables in the template.

It takes one or multiple semicolon-separated variable definitions.

Making a shortcut to a long path:

<div tal:define="destname path/to/existing/variable">…</div>

Defining more than one variable at the same time:

<span tal:define="fname string:Paul; lname string:Dupond">…</span>

Each definition may start with global keyword which makes variable available everywhere later in the template and all macros. Global variables can be redefined.

<span tal:define="global hello string:hello world"/>
<p tal:content="hello"/>

On the contrary, a local variable is only available inside the element it is defined in (and inside marcos that are called in this element):

<span tal:define="hello string:hello world"/>
<p tal:content="hello"/> <!-- will produce an undefined variable error -->

Tip

You may also use tal:define with other attributes, it will be executed before any other attributes on the same element.

Creating a string inside the template:

<span tal:define="destname string:some string" />

Defining a string containing another variable:

<span tal:define="fname string:Paul; hello string:Hello $fname! Welcome to this page" />

A small trick which uses content of the element (useful if you need to define very complex value):

<span tal:define="global hello">Hello ${fname}! Welcome to this page</span>

In above example, the <span> tag won't show up because it has no printable content (hello variable grabs it) nor attributes.

Note

This is a special case. It only works if you use the global keyword.

tal:condition

The element and its content will be shown only if the condition is evaluated to true.

<p tal:condition="identified"> Welcome member … </p>

<p tal:condition="not: identified">
  Please login before accessing this page
</p>

If the PHP backend does not provide your templates with enough methods, you will often have to fall back to PHP for special conditions:

<span tal:comment="show only if more than five items in the cart"
      tal:condition="php: cart.countItems() GT 5">…</span>

This may put too much logic inside the template and it is sometimes preferable to provide boolean attributes or accessible methods to the template:

<span tal:condition="cart/hasEnoughItems">…</span>

tal:repeat

This attribute handles iterable objects like arrays, associative arrays, and objects implementing the PHP5 Iterator class.

The repeat attribute repeats its element and its content until the end of the specified resource.

<tr tal:repeat="item some/result">
  <td tal:content="item">text replaced by item</td>
</tr>

Within a loop, you can access the current loop information (and that of its parent for nested loops) using specific repeat/* paths.

In the above example:

  • repeat/item/key : returns the item's key if some/result is an associative resource (index otherwise)

  • repeat/item/index : returns the item index (0 to count-1)

  • repeat/item/number : returns the item number (1 to count)

  • repeat/item/even : returns true if item index is even

  • repeat/item/odd : returns true if item index is odd

  • repeat/item/start : returns true if item is the first one

  • repeat/item/end : returns true if item is the last one

  • repeat/item/length : returns the number of elements in some/result

"item" depends on the receiver variable defined in tal:repeat expression.

The most common usage of tal:repeat is in using some SQL database result. The following code will work if playersRanking contains object that implements PHP's Iterator interface:

<table>
  <thead>
    <tr>
      <th>Position</th>
      <th>Player</th>
      <th>Score</th>
    </tr>
  </thead>
  <tbody>
    <tr tal:repeat="ranking playersRanking">
      <td tal:content="ranking/position"/>
      <td tal:content="ranking/player"/>
      <td tal:content="ranking/score"/>
    </tr>
  </tbody>
</table>

tal:omit-tag

This attribute asks the PHPTAL parser to ignore the elements's open and close tag, its content will still be evaluated.

<span tal:omit-tag="condition">
  if the condition is true, then only this text will appear and span open and close will be removed
</span>

Will produce:

only this text will appear, span open and close will be removed

This attribute is useful when you want to create element optionally, e.g. hide a link if certain condition is met.

If you want element that is never output, you can use tal:block

<tal:block tal:repeat="x php:range(1,10)">only this text will appear, ten times.</tal:block>

tal:replace

This attribute will replace the entire tag with a value, or by nothing if no value is given.

<span tal:replace="string:this beautiful string">
  this ugly string and span
</span>

Will produce:

this beautiful string

tal:replace can also be used to create samples in source templates, but remove them from final output.

<table>
  <tr tal:repeat="item myresult">
    <td tal:content="item">item value</td>
  </tr>
  <tr tal:replace="">
    <td>sample 1</td>
  </tr>
  <tr tal:replace="">
    <td>sample 2</td>
  </tr>
</table>

tal:content

This attribute replaces the tag content with the evaluation of its expression.

<span tal:define="myvar string:my string"/>
<span tal:content="myvar">will be replaced</span>

Will produce:

<span>my string</span>

tal:attributes

This attribute changes tag attribute(s) value(s).

<a href="http://www.foo.com" title="some foo link"
   tal:attributes="href somelink/href; title somelink/title"
  tal:content="somelink/text"
>sample link</a>

With a 'somelink' having:

$somelink->href = "http://www.google.com";
$somelink->title = "google search engine";
$somelink->text = "the google search engine";

Will produce:

<a href="http://www.google.com"
title="google search engine">the google search engine</a>

Semicolon (;) separates attributes. If you want semicolon to be output in an attribute, you have to double it (;;).

A somewhat complicated example involving tal:repeat:

<tr tal:repeat="ranking playerRankings"
    tal:attributes="class php: repeat.ranking.odd ? 'odd' : NULL">
    …
</tr>

The php: modifier will be explained later, basically if the line is odd then tr will have a class attribute with "odd" as value, otherwise, no class will be set.

The "condition ? then : else" is a regular PHP expression which must be used with care but has proven to be useful on more than one occasion.

A better way to achieve the same result would be to ask your PHP coder to create a custom modifier for your needs (see PHP integration / custom modifiers) which would be used as follows:

<tr tal:repeat="ranking playerRankings"
    tal:attributes="class css-odd:repeat/ranking/odd">
  …
</tr>

The modifier would return "odd" if repeat/ranking/odd is true, NULL otherwise.

Optional attributes

If you use TALES alternatives in tal:attributes and use nothing (or NULL in PHP) as last alternative, attribute won't be added at all if there's no value for it (this avoids adding empty attributes):

… tal:attributes="title object/tooltip | nothing">

XHTML attributes like selected, checked, etc. are properly handled automatically.

<input type="checkbox" tal:attributes="checked object/isChecked"/>

Warning

Remember that XHTML is case-sensitive, so SELECTED attribute is an error in XHTML. Use selected.

tal:on-error

This attribute replaces the tag by the tal:on-error expression evaluation if a path error is detected in the tag content, or if any PHP exception is thrown in the tag content.

<span tal:on-error="string:No username defined here"
      tal:content="user/name">the user name here</span>

If an error occurs accessing 'name' or 'user', the error string will be shown at the tag's place.

This also works on more than one level of template:

<span tal:on-error="string:error occurred somewhere">
  <span tal:content="user/firstname"/>
  <span tal:content="user/lastname"/>
  <span metal:use-macro="userMenu" />
</span>

METAL namespace

  1. metal:define-macro
  2. metal:use-macro
  3. metal:define-slot
  4. metal:fill-slot

URI for this namespace is http://xml.zope.org/namespaces/metal. To use metal: attribute prefix in XML you're required to declare it:

<html xmlns:metal="http://xml.zope.org/namespaces/metal" …>

Note

PHPTAL does not enforce this requirement.

METAL stands for 'Macro Extension for TAL'. This namespace allows template designers to define and call macros. Macros can be used to output data recursively or to include code from other template files.

metal:define-macro

This attribute declares a macro. Think of macros as library of small templates which can be reused in any other template.

<div metal:define-macro="main_menu">
  <ul>
    <li><a href="/">home</a></li>
    <li><a href="/products">products</a></li>
    <li><a href="/contact">contact</a></li>
  </ul>

  <div>
    Last modified:
    <span tal:content="mdate">page modification date</span>
  </div>
</div>

Macros inherit all variables from their caller. In the above example, the variable 'mdate' depends on the template that calls the macro.

metal:use-macro

This attribute calls a macro and includes its result in the current template.

<span
  tal:comment="main_menu template requires 'mdate' variable"
  tal:define="mdate page/last_modified"
  metal:use-macro="main_menu"
/>

You can refer to external macros defined in other templates by specifying the template source file.

<span metal:use-macro="site_macros.xhtml/main_menu"/>

It is interesting to note that you can also use the PHPTAL inline replacement feature inside the use-macro attribute value:

<span metal:use-macro="${design}/site_macros.xhtml/main_menu"/>

Macro can call itself. This way you can output arrays recursively:

<ul metal:define-macro="show-list">
    <li tal:repeat="item list">
        <tal:block tal:condition="php:is_array(item)" tal:define="list item" metal:use-macro="show-list" />
        <tal:block tal:condition="php:!is_array(item)" tal:content="item" />
    </li>
</ul>

metal:define-slot

This attribute must appear inside a metal:define-macro tag.

Slots can be replaced by caller template with some custom dynamically-generated XML/XHTML.

Slots can be thought of like reverse includes, a macro can be an entire page and slots customize this page depending on the URL. For instance, a slot may contain the latest news in the home page or user actions when the member is logged in.

<span metal:define-slot="news_place">
  <table>
    <tr tal:repeat="item php:latestNews()">
      <td tal:content="item/value">news description</td>
    </tr>
  </table>
</span>

The above example defines a place called 'news_place' which can be overwritten by caller templates. See next section for the continuation of this example.

metal:fill-slot

This attribute can occur only inside metal:use-macro element.

This explicitly tells PHPTAL to replace a defined slot with the content provided inside the metal:fill-slot attribute.

<span tal:condition="logged" metal:fill-slot="news_place">
  <h2>user menu</h2>
  <ul>
    <li><a href="/user/action/inbox">inbox</a></li>
    <li><a href="/user/action/new">new mail</a></li>
    <li><a href="/user/action/disconnect">disconnect</a></li>
  </ul>
</span>

Slots give the opportunity to define really customizable and reusable page templates with a simple push technology.

I18N namespace

  1. i18n:translate
  2. i18n:attributes
  3. i18n:name
  4. XHTML in translations

URI for this namespace is http://xml.zope.org/namespaces/i18n. To use i18n: attribute prefix in XML you're required to declare it:

<html xmlns:i18n="http://xml.zope.org/namespaces/i18n" …>

Note

PHPTAL does not enforce this requirement.

Note

i18n is a short name for 'internationalization'. This namespace allow template designers to specify some text zones that must be translated during template evaluation.

i18n:translate

This attribute defines some text part that must be translated using PHPTAL's translation system.

<div i18n:translate="string:welcome_message">Welcome here</div>

In the above example, PHPTAL will looks for a translation key named 'welcome_message' and will replace the content of the tag with the equivalent in currently requested language.

<div i18n:translate="">Welcome here</div>

This usage is a little different, no translation key is given, thus PHPTAL will use the content of the tag 'Welcome here' as the translation key. This is a regular translation if translation system knows the key 'Welcome here'.

If no translation is found, the key will be used as the translation result. That's why using readable message instead of keys may be a good choice.

Please note that the key to translate may be contained in a variable, to allow dynamic key selection.

<div tal:define="welcome random_welcome_message">
  <div i18n:translate="welcome">…</div>
</div>

i18n:attributes

Defines which attributes should be translated. Takes semicolon-separated list of attributes and keys similar to those for i18n:translate.

<img i18n:attributes="alt 'picture alternative text';title thetitle" alt="Picture" title="${thetitle}" />

i18n:name

This attribute sets a translation variable value.

Translations may contain ${xxx} strings where "xxx" is the name of a variable that needs to be interpolated dynamically.

The value of this variable will be set to the tag and its content. If you don't need the tag around the value, use tal:replace instead of tal:content. tal:omit-tag may help if the value is a concatenation of strings.

<span i18n:name="myVar" tal:content="some/path"/>
<!-- <span>${some/path}</span> -->

<span i18n:name="myVar" tal:replace="some/path"/>
<!-- ${some/path} -->

<span i18n:name="myVar">foo</span>
<!-- <span>foo</span> -->

<span i18n:name="myVar" tal:omit-tag="">foo</span>
<!-- foo -->

An example of i18n usage:

<div i18n:translate="">
  Welcome <span i18n:name="user" tal:replace="user/name"/>,
  you have <span i18n:name="mails" tal:replace="user/nbrMails"/>
  unread mails.
</div>

The translation key of this example will be:

"Welcome ${user}, you have ${mails} unread mails."

PHPTAL will replace ${user} with ${user/name} and ${mails} with ${user/nbrMails} in translation.

More information about I18N with PHPTAL is available in the PHP section of this book.

XHTML in translations

By defaults translations are assumed to contain only text, so PHPTAL escapes all "<" characters.

You can use structure keyword in i18n:translate to disable escaping and use translated text as-is:

<div i18n:translate="structure '<b>bold text</b>'" />

Gives:

<div><b>bold text</b></div>

Warning

Caveats: This will only work in simplest cases – TAL attributes inside translated strings are ignored. Ill-formed XHTML in translations will break page well-formedness.

PHPTAL namespace

  1. phptal:debug
  2. phptal:cache
    1. Instant refreshing
    2. Limitations:
  3. phptal:tales

URI for this namespace is http://phptal.org/ns/phptal. To use phptal: attribute prefix in XML you're required to declare it:

<html xmlns:phptal="http://phptal.org/ns/phptal" …>

Note

PHPTAL does not enforce this requirement.

These attributes are not defined in TAL specifications, but are useful when working with PHPTAL.

phptal:debug

This attribute toggles the activation of PHPTAL debugging for the content of the tag it is defined in.

Note

To debug errors in macros called across templates you need to add phptal:debug in template which defines the macro, not the one which uses it.

The debug mode stores information like filename and source line number in the template, so exceptions thrown by incorrect path access will contain more information about where they where thrown.

<html>
  <head>
    …
  </head>
  <body>
    <div id="menu">
      …
    </div>
    <div id="leftPane" phptal:debug=""
      tal:comment="this div seems buggy, keep
      trace of where errors are thrown">
          …
    </div>
  </body>
</html>

phptal:cache

This attribute causes output of entire element (including its tag) to be cached on disk and not re-evaluated until cache expires.

Note

Use of cache is beneficial only for elements that use very complex expressions, macros from external files or PHP expressions/objects that access the database. Otherwise uncached templates will be just as fast.

Content of this attribute is a duration (how long element should be kept in cache) written as number with 'd', 'h', 'm' or 's' suffix.

<div class="footer" phptal:cache="3h">…</div>

<div> will be evaluated at most once per 3 hours.

Duration can be followed by optional "per" parameter that defines how cache should be shared. By default cache is shared between all pages that use that template. You can add "per url" to have separate copy of given element for every URL.

<ol id="breadcrumbs" phptal:cache="1d per url">…</ol>

<ol> will be cached for one day, separately for each page.

You can add "per expression" to have different cache copy for every different value of an expression (which MUST evaluate to a string).

Note

Expression cannot refer to variables defined using tal:define on the same element.

<ul id="user-info" phptal:cache="25m per object/id">…</ul>

<ul> will be cached for 25 minutes, separately for each object ID.

Warning

Be careful when caching users' private data. Cache will be shared with everyone unless you make it user-specific with per user/id or similar expression.

Instant refreshing

Instead of clearing cache, it might be a better idea to put version or last modification timestamp in the per parameter. This will cause cached template to be refreshed as soon as version/timestamp changes and no special cache clearing will be neccessary.

<div phptal:cache="100d per php:news.id . news.last_modified_date">…</div>

Limitations:

  • phptal:cache blocks can be nested, but outmost block will cache other blocks regardless of their freshness.

  • You cannot use metal:fill-slot inside elements with phptal:cache.

phptal:tales

This attribute allows us to change the behaviour of PHPTALES. The default behaviours is to interpret attribute expressions in a very ZPT way. But sometimes you just would like to have PHP there, and you end up using php: modifier everywhere.

Another problem concerning PHPTALES is the way PHPTAL has to interpret paths. For example, myobject/mymethod/property/10/othermethod/hashkey takes relatively long to interpret (but don't worry about this too much – don't optimize until you find that it is really a problem with performance!)

PHPTAL has (at runtime) to take myobject and discover that it is an object; find out that 'mymethod' is a method of this object (rather than a variable), and then to call it; explore the result to determine that it is an object with a property; find that its value is an array; find the 'ten' element of this array, and determine that it is an object; decide that othermethod is a method of this object (rather than a variable), and get the result of its execution; find that it is an object, and then retrieve the value for the key 'hashkey'.

Of course this was an extreme example and most of the time we don't care, because the process is fast enough. But what if this very long path is called inside a big tal:repeat? D'oh! phptal:tales can help us here:

<html>
  <body>
    <table phptal:tales="php">
      <tr tal:repeat="myobject document.getChildren()">
        <td
          tal:content="myobject.mymethod().property[10].otherMethod().hashkey"></td>
      </tr>
    </table>
  </body>
</html>

Please note that the above example does the same as:

<html>
  <body>
    <table>
      <tr tal:repeat="myobject php:document.getChildren()">
        <td
          tal:content="php:myobject.mymethod().property[10].otherMethod().hashkey"></td>
      </tr>
    </table>
  </body>
</html>

Note

php: modifier is explained in its own chapter.

tal:block

tal:block is a syntactic sugar for elements which contains many TAL attributes which are not to be echoed.

<tal:block define="myvar string:Some value"/>

is the same as:

<span tal:define="myvar string:Some value" tal:omit-tag=""/>

Another example:

<tal:block condition="someCondition" repeat="item someRepeat">
  <div metal:use-macro="x"/>
</tal:block>

is the same as:

<div tal:omit-tag=""
     tal:condition="someCondition"
     tal:repeat="item someRepeat">
  <div metal:use-macro="x"/>
</div>

PHPTALES

  1. path:
  2. Alternative PHP operator syntax
  3. string:
  4. php:
  5. not:
  6. exists:
  7. default
  8. structure
  9. Expression chains

PHPTALES is the equivalent of TALES, the Template Attribute Language Expression Syntax which is the syntax used inside TAL, METAL, PHPTAL attributes and ${…} inline expressions.

In previous examples, you should have seen some PHPTALES examples (string:, php:, not:, …). This chapter describes the usage of PHPTALES in templates.

The value of a TAL attribute may contain more than one expression (ex: tal:define), in which case each expression must be separated from the next one with a ';' character.

path:

This is the default modifier used in TAL expression when no other modifier is specified.

The following lines will give the same result:

<span tal:content="data/user/name"/>
<span tal:content="path:data/user/name"/>
<span>${data/user/name}</span>

Inside the template or inside expression strings, you can refer to a context variable using its path in the form ${path/to/my/variable}

<h1>${document/title}</h1>
<span tal:replace="string:welcome ${user/name},
this page has been readed ${page/countRead} times"/>

Warning

If you try to read variable that does not exist, PHPTAL will throw an exception. Use exists: to check if variable can be read

Alternative PHP operator syntax

Because '<', '>' and '&' characters are cumbersome to use in XML, PHPTAL provides alternative syntax for PHP operators using these characters, and a few more for consistency.

These operators can be used only in php: expressions.

  • < : LT (less than)

  • > : GT (greater than)

  • <= : LE (less or equal)

  • >= : GE (greater or equal)

  • == : EQ (equal)

  • != : NE (not equal)

  • && : AND

  • || : OR

string:

Because expressions are separated by a ';' character, and because '$' marks the start of a path, you must use:

  • ';;' when you want to insert a real ';' character in a string,

  • '$$' when you want to insert a real '$' character in a string.

<span tal:replace="string:this is a $$100 page"/>
string:foo $bar baz       <!-- will replace $bar -->
string:foo $$bar baz      <!-- no interpolation -->
string:foo ; php:doFoo()  <!-- two different expressions -->
string:foo ;; php:doFoo() <!-- only string -->

php:

This expression evaluates what follows as a regular PHP expression except that '->' is replaced by dots '.' and variable names are prefixed with a dollar '$' sign.

A dot '.' separated from the rest of expression by spaces is assumed to be a concatenation sign.

php:htmlentities(foo)
php:'string ${varReplaced}'
php:'string ${some.path().to[0].var}'
php:NOT foo OR (bar GT baz)
php:a + b
php:array('a', 'b', 'c')
php:range(0, 90)
php:foo . a.b.c(e) . htmlentities(SomeClass::staticMethod())
php:SomeClass::ConstOfClass
php:SomeClass::$staticVar

php: should be used with care and won't be needed in 80% of your templates but sometimes you will need to invoke some special PHP method to be certain whether a user is logged in, or to retrieve specific complex data depending on some conditions, dynamically inside the template.

not:

This expression is a boolean one, useful in tal:condition statements.

<span tal:condition="not: logged">not logged</span>

exists:

This expression returns true if the path specified after it exists, and false otherwise. It is analogous to PHP's isset().

Normally using a path which doesn't exist throws an error like "Cannot find variable 'foo' in current scope". Thus, uncertain paths must be checked first:

<span tal:condition="exists:user/preferences" tal:content="user/preferences">
  Use user/preferences here if defined
</span>

Tip

In PHPTALES use isset() instead.

default

This is not an expression but a keyword, allowing template designers to keep the content of a tag as an alternative value if an error occurs, or if something is not defined.

<span tal:define="myVar path/to/possible/var | default">
  default my var value
</span>

<span tal:content="some/var | other/path | default">
  no some/var and no other/path found here
</span>

<a href="unknown.xhtml" title="Unknown page"
   tal:attributes="href item/href | default; title item/title | default"
   tal:content="item/title | default">Unknown page</a>

Above examples introduce the '|' character that allows the definition of alternatives for defines or prints.

structure

This is not an expression modifier but a keyword.

While printing variables inside PHPTAL templates, you will have noticed that PHPTAL encodes each variable to ensure the validity of the output document.

Sometimes, you may use HTML/XML variables which must be echoed as is.

<h1 tal:content="structure document/title"/>
<span tal:replace="structure document/content"/>

In above examples, we assume that $document->title and $document->content are variables containing preformated HTML which must be echoed as is.

Expression chains

An expression chain is a list of expressions separated by '|' characters.

While evaluating expressions separated by '|', PHPTAL will stop its evaluation when an expression value is not null and no error was raised while evaluating the expression.

As a string: expression is always true, string: always terminates an expression chain whatever expression may follow.

You can use php: expressions inside expression chains, like any other expression.

<h1 tal:content="page/title | page/alternativeTitle | php:get_default_title()" />

PHP Integration

Table of Contents

  1. Constants
  2. Configuration methods
    1. setOutputMode(mode)
    2. setEncoding(encoding)
    3. Other methods
      1. setTemplateRepository(string_or_array)
      2. setPhpCodeDestination(path)
      3. setPhpCodeExtension(string)
      4. setCacheLifetime(num_days)
      5. setForceReparse(boolean)
  3. class PHPTAL
    1. echoExecute() method
      1. Limitations
  4. interface PHPTAL_Filter
  5. interface PHPTAL_Trigger
  6. interface PHPTAL_TranslationService
    1. method setLanguage(…)
    2. method useDomain($domain)
    3. method setVar($key,$value)
    4. method translate($key)
    5. method setEncoding($encoding)
  7. Working with gettext
    1. Creating the translation directory structure
    2. Portable Object files
    3. Translation Domain
    4. Using Translator in PHP
    5. Variable interpolation
  8. Creating custom expression modifiers

This section is aimed at PHP developers and explains how to use and customize PHPTAL behaviours for simple and advanced usage.

  • PHPTAL: the main PHPTAL class. It is used to load and execute templates.

  • PHPTAL_Filter: filtering template sources and PHPTAL output.

  • PHPTAL_Trigger: handles output of elements with phptal:id.

  • PHPTAL_TranslationService: for replacing the built-in gettext support with your own internationalization system.

Constants

The only constant defined in PHPTAL.php is PHPTAL_VERSION. It contains version of PHPTAL library installed on your system (in format: X.X.X).

In older versions of there were constants for configuration. They have been removed in favour of methods.

Configuration methods

  1. setOutputMode(mode)
  2. setEncoding(encoding)
  3. Other methods
    1. setTemplateRepository(string_or_array)
    2. setPhpCodeDestination(path)
    3. setPhpCodeExtension(string)
    4. setCacheLifetime(num_days)
    5. setForceReparse(boolean)

PHPTAL tries to use best defaults possible and you shouldn't need to change any of the settings.

All of these are methods of the PHPTAL class. set* methods return instance of their class, so you can chain them:

<?php
  echo $phptal->setPhpCodeDestination('/tmp/phptal')->setOutputMode(PHPTAL::XML)->setTemplate('tpl.zpt')->execute();
?>

is the same as:

<?php
  $phptal->setPhpCodeDestination('/tmp/phptal');
  $phptal->setOutputMode(PHPTAL::XML);
  $phptal->setTemplate('tpl.zpt');
  echo $phptal->execute();
?>

There are other set* methods for filters, internationalisation, etc. They have been described in other sections of this manual.

setOutputMode(mode)

Changes what syntax is used when generating elements. Valid modes are:

PHPTAL::XHTML

In this mode (which is default) PHPTAL will output XHTML in a way that is backwards-compatible with HTML browsers.

  • Empty elements will be forced to use self-closing form (<img/>, <link/>), and non-empty elements will always have closing tag.

    Warning

    XHTML output mode changes <link> element in way that is incompatible with RSS. Use XML output mode to generate RSS feeds or use Atom.

  • Boolean attribtes (checked, selected, etc.) will always have value required by the XHTML specification (it simplifies use of tal:attributes).

  • <![CDATA[ blocks will be added or removed automatically and will use special escaping syntax that is safe in both XML and HTML.

    Tip

    If you're always sending XHTML as application/xhtml+xml, then it's better to use XML output mode.

PHPTAL::HTML5

This mode generates documents that have best compatibility with text/html parsing in current web browsers, but are not XML.

PHPTAL will change DOCTYPEs to <!DOCTYPE html>. Namespace declarations, name prefixes, explicit CDATA sections and other HTML-incompatible constructs will be ommited.

Note

This mode is not a "tag soup". PHPTAL will close all elements properly and quote attributes when it's necesary. Output will be properly formatted HTML 5, and fully backwards-compatible with current HTML 4 browsers.

PHPTAL::XML

This mode outputs "pure" XML without compatibility with text/html parsing. Use this mode when generating feeds, SVG, MathML, RDF and other XML files.

setEncoding(encoding)

Specify charcter encoding used by your templates. The default is UTF-8.

PHPTAL assumes that encoding of all templates and generated documents is the same. BOM (Byte Order Marker) is removed from UTF-8 documents.

Note

PHPTAL does not read encoding from XML files and never converts character encodings.

Tip

Save yourself trouble and always use UTF-8 for everything.

Other methods

setTemplateRepository(string_or_array)

Specifies where to look for templates. If given a string, it adds it to the list of paths searched. If given array, it replaces the list.

This doesn't mean all your files need to be in the root directory, you can use sub folders to organize your template designer's work. It's just a shortcut which will allow you to reference templates without specifying the real path, but instead their relative path within the repository.

Tip

It's like include_path, but for PHPTAL templates only.

setPhpCodeDestination(path)

To tell PHPTAL where to store its intermediate (temporary) PHP files. By default it uses directory given by PHP's sys_get_tmp_dir(), which usually is '/tmp/' directory.

setPhpCodeExtension(string)

What filename extension should be used for intermediate PHP files. The default is php and frankly, there's no reason to change it.

setCacheLifetime(num_days)

Maximum number of days intermediate files and fragments cached with phptal:cache should be kept.

setForceReparse(boolean)

Forces reparsing of all templates all the time. It should be used only for testing and debugging. It's useful if you're testing prefilters or changing code of PHPTAL itself.

Warning

This slows down PHPTAL very much. Never enable this on production servers!

class PHPTAL

  1. echoExecute() method
    1. Limitations

This is the main library class for you to use.

The most common method of use:

<?php

// include the library
require_once 'PHPTAL.php';

// instantiate a new PHPTAL object using specified template file
$tpl = new PHPTAL('mytemplate.xhtml');

// setting some template context variables
$tpl->title  = 'my title';
$tpl->values = array(1,2,3,4);
$tpl->user   = new User('Joe');

// execute the template and echo the result in a 'secure' way
try {
    echo $tpl->execute();
}
catch (Exception $e){
    echo "Exception thrown while processing template\n";
    echo $e;
}
?>

You can perfectly well choose to specify the template source after setting context variables.

<?php
…
$tpl = new PHPTAL();

// it is a matter of taste but you can use the set() method instead of
// setting context using PHPTAL::__set() like above
$tpl->set('title', 'my title');
$tpl->set('values', array(1,2,3,4));
$tpl->set('user', new User('Joe'));

$tpl->setTemplate('mytemplate.xhtml');
…
?>

You can also decide to use a generated string as the template source instead of using an existing template file:

<?php

$src = <<<EOS
<html>
  <head>
  <title tal:content="title">my title</title>
  </head>
  <body>
    <h1 tal:content="title">my title</h1>
  </body>
</html>
EOS;

require_once 'PHPTAL.php';
$tpl = new PHPTAL();
$tpl->setSource($src);
$tpl->title = 'this is my title';
try {
    echo $tpl->execute();
}
catch (Exception $e){
    echo $e;
}

?>

In the above example, because PHPTAL requires a template source identifier (usually the template file realpath), PHPTAL will use the md5 of the $src parameter as a unique identifier. You may decide to force the identifier using a second setSource() argument:

<?php
$src = <<<EOS
<html>
  <head>
  <title tal:content="title">my title</title>
  </head>
  <body>
    <h1 tal:content="title">my title</h1>
  </body>
</html>
EOS;

require_once 'PHPTAL.php';
$tpl = new PHPTAL();

// If you specify where the source comes from (second argument to setSource),
// PHPTAL will be able to generate more helpful error messages.
$tpl->setSource($src, __FILE__);
$tpl->title = 'this is my title';
try {
    echo $tpl->execute();
}
catch (Exception $e){
    echo $e;
}

?>

echoExecute() method

Since most common use of execute() method is to echo its output, PHPTAL offers convenience method that echoes output immedately without buffering. This enables streaming of arbitrarily large output without hitting memory limit.

Note

Fragments of template that use tal:on-error or phptal:cache are buffered regardless.

The code:

<?php
    $tpl = new PHPTAL('template.xhtml');
    $tpl->echoExecute();
?>

is same as:

<?php
    $tpl = new PHPTAL('template.xhtml');
    echo $tpl->execute();
?>

but little faster.

Warning

Currently echoExecute() method has some unexpected limitations.

Limitations

When echoExecute() is used, PHPTAL will throw exception if you call any macro defined in a file that has XML declaration or DOCTYPE.

Typically PHPTAL allows templates to "inherit" DOCTYPE from another file (useful when subpage is calling main layout template), however that is not possible without buffering.

To work around this you can:

  • Keep using echo $tpl->execute() until this limitation is removed.

  • Remove all DOCTYPEs and XML declarations from templates and echo them from PHP before calling echoExecute().

interface PHPTAL_Filter

This interface allows you to automatically filter templates sources (pre-filters) or PHPTAL result (post-filters).

Pre filters are invoked before the template parsing and won't be invoked until the source template file is modified.

Post filters are invoked after each template execution.

<?php
require_once 'PHPTAL.php';

class MyPreFilter implements PHPTAL_Filter {
    public function filter($source){
        return $source;
    }
}

class MyPostFilter implements PHPTAL_Filter {
    public function filter($xhtml){
        return $xhtml;
    }
}

$tpl = new PHPTAL('mytemplate.xhtml');
$tpl->setPreFilter(new MyPreFilter());
$tpl->setPostFilter(new MyPostFilter());
echo $tpl->execute();
?>

You can set only one pre-Filter and one post-Filter using set*Filter. If you have more than one filter to chain, you can wrap them into a single class, implementing the PHPTAL_Filter interface, which would invoke the filter's chain.

<?php
require_once 'PHPTAL.php';

class FilterChain implements PHPTAL_Filter {
    private $_filters = array();

    public function add(PHPTAL_Filter $filter){
        $this->_filters[] = $filter;
    }

    public function filter($source){
        foreach($this->_filters as $filter){
            $source = $filter->filter($source);
        }
        return $source;
    }
}

$myfilter = new FilterChain();
$myfilter->add(new CommentFilter());  // imaginary filter
$myfilter->add(new TidyFilter());     // imaginary filter

$tpl = new PHPTAL('mytemplate.xhtml');
$tpl->setPostFilter($myFilter);
echo $tpl->execute();
?>

interface PHPTAL_Trigger

The phptal:id attribute was added into the PHPTAL for the PHP5 version to replace the old PHPTAL_Cache interface and to abstract it a little more.

When a phptal:id is reached, PHPTAL will look in its triggers list for a matching id and will invoke the trigger start() and end() methods before entering the element, and just after it.

If the PHPTAL_Trigger::start() method returns PHPTAL_Trigger::SKIPTAG, PHPTAL will ignore the element and its content (start() may echo something to replace it).

If your trigger wants the element and its content to be executed, you'll have to return PHPTAL_Trigger::PROCEED.

The PHPTAL_Trigger::end() will be called after the element (whether it has been executed or not). This allows you to build cache systems using ob_start() in start() and ob_get_contents(), ob_end_clean() in end().

<html>
  …
  <div>
    …
    foo bar baz <span tal:replace="id"/> foo bar baz
    …
  </div>
  …
</html>

For some reason we decide the <div> block requires to be cached. We introduce a phptal:id into the template:

<html>
  …
  <div phptal:id="somePossiblyUniqueKeyword">
    …
    foo bar baz <span tal:replace="id"/> foo bar baz
    …
  </div>
  …
</html>

Then we write our trigger which will cache the <div> content:

<?php
require_once 'PHPTAL.php';
require_once 'PHPTAL/Trigger.php';

class CacheTrigger implements PHPTAL_Trigger
{
    public function start($phptalid, $tpl)
    {
        // this cache depends on 'id' which must appears in
        // the template execution context
        $this->_cachePath = 'cache.' . $tpl->getContext()->id;

        // if already cached, read the cache and tell PHPTAL to
        // ignore the tag content
        if (file_exists($this->_cachePath)){
            $this->_usedCache = true;
            readfile($this->_cachePath);
            return self::SKIPTAG;
        }

        // no cache found, we start an output buffer and tell
        // PHPTAL to proceed (ie: execute the tag content)
        $this->_usedCache = false;
        ob_start();
        return self::PROCEED;
    }

    // Invoked after tag execution
    public function end($phptalid, $tpl)
    {
        // end of tag, if cached file used, do nothing
        if ($this->_usedCache){
            return;
        }

        // otherwise, get the content of the output buffer
        // and write it into the cache file for later usage
        $content = ob_get_contents();
        ob_end_clean();
        echo $content;

        $f = fopen($this->_cachePath, 'w');
        fwrite($f, $content);
        fclose($f);
    }

    private $_cachePath;
    private $_usedCache;
}
?>

The key here is to return from start() with either SKIPTAG or PROCEED.

When SKIPTAG is returned, PHPTAL will just ignore the tag and call end(). This usually means that the trigger takes the hand in deciding what to show there.

When PROCEED is returned, PHPTAL will execute the tag and its content as usual, then call end(). This allows our cache class to play with output buffers to execute the tag once and to store the result in a file which will be used in later calls.

To install our trigger we use:

<?php
require_once 'PHPTAL.php';
require_once 'CacheTrigger.php'; // our custom trigger

$trigger = new CacheTrigger();

$tpl = new PHPTAL('test.xhtml');

// this trigger will only be called for phptal:id="triggerId"
$tpl->addTrigger('somePossiblyUniqueKeyword', $trigger);

$tpl->id = 1;

echo $tpl->execute();

?>

You can add as many triggers as you like to your templates. A generic cache trigger may also handle more than one phptal:id… etc…

interface PHPTAL_TranslationService

  1. method setLanguage(…)
  2. method useDomain($domain)
  3. method setVar($key,$value)
  4. method translate($key)
  5. method setEncoding($encoding)

PHPTAL comes with a default gettext translation service, as shown in another section. For some reason you may prefer to implement your own service of translation.

The PHPTAL_TranslationService interface is here to serve your needs.

The usage of your service will be the same as the PHPTAL_GetTextTranslator.

$tpl->setTranslator($yourOwnTranslatorInstance);

Your implementation must define the following methods:

method setLanguage(…)

This method may be called by the template to change the current output language and/or locale (e.g. en_US).

Its arguments are a list of possible languages. Use func_get_args() to get the argument array. The first known language should be used by your service.

Return language that has been set.

<?php
require_once 'PHPTAL/TranslationService.php';

class MyTranslator implements PHPTAL_TranslationService {
…
    public function setLanguage(){
        $langs = func_get_args();
        foreach($langs as $lang){
            // if $lang known use it and stop the loop
            $this->_currentLang = $lang;
            break;
        }
        return $this->_currentLang;
    }
    …
    private $_currentLang;
}
?>

method useDomain($domain)

If you decided to store your translations into separate files, one for each application, for example, this method allows you to select the translation domain from your templates (i18n:domain).

<?php
require_once 'PHPTAL/TranslationService.php';

class MyTranslator implements PHPTAL_TranslationService {
    …
    public function useDomain($domain){
        if (!array_key_exists($domain, $this->_domains)){
            $file = "domains/$this->_currentLang/$domain.php";
            $this->_domains[$domain] = include($file);
        }
        $this->_currentDomain = $this->_domains[$domain];
    }
    …
    private $_currentDomain;
    private $_domains = array();
}
?>

The above example is a possible translation solution where keys are stored in PHP files which return an associative array of key => translation.

method setVar($key,$value)

This method matches i18n:name calls. It builds an interpolation context for later translate calls.

<?php
require_once 'PHPTAL/TranslationService.php';

class MyTranslator implements PHPTAL_TranslationService {
    …
    public function setVar($key, $value){
        $this->_context[$key] = $value;
    }
    …
    private $_context = array();
}
?>

method translate($key)

The last and most important method to implement, it asks your service to translate the specified key for the currently selected language.

<?php
require_once 'PHPTAL/TranslationService.php';

class MyTranslator implements PHPTAL_TranslationService {
    …
    public function translate($key){
        $value = $this->_currentDomain[$key];

        // interpolate ${myvar} using context associative array
        while (preg_match('/\${(.*?)\}/sm', $value, $m)){
            list($src,$var) = $m;
            if (!array_key_exists($var, $this->_context)){
                $err = sprintf('Interpolation error, var "%s" not set',
                               $var);
                throw new Exception($err);
            }
            $value = str_replace($src, $this->_context[$var], $value);
        }

        return $value;
    }
    …
}
?>

method setEncoding($encoding)

PHPTAL class calls this method to inform your translation service what encoding is used by the template. translate() method should return strings in that encoding. If you always use the same encoding for templates and translation files (i.e. UTF-8), you can leave this method empty.

Working with gettext

  1. Creating the translation directory structure
  2. Portable Object files
  3. Translation Domain
  4. Using Translator in PHP
  5. Variable interpolation

gettext is a standard GNU internationalization / translation system which can be used with PHP and which is supported by PHPTAL.

The usage of gettext™ is simple but you will have to perform some tests to be sure everything works fine on your system.

First, PHP must be compiled with the --with-gettext flag. See PHP documentation for how to do this.

You can test your installation using following peace of code:

//
// test if gettext extension is installed with php
//

if (!function_exists("gettext"))
{
    echo "gettext is not installed\n";
}
else
{
    echo "gettext is supported\n";
}

Creating the translation directory structure

The PHP gettext™ extension requires a specific structure which will contain your translation files.

/path/to/your/translation_root/en_US/LC_MESSAGES/
/path/to/your/translation_root/en_GB/LC_MESSAGES/
/path/to/your/translation_root/fr_FR/LC_MESSAGES/
/path/to/your/translation_root/es_ES/LC_MESSAGES/
… and so on …

The language code is composed of two characters defining the language itself (en, fr, es, …) and two characters defining the country (US, GB, FR, ES, …).

The directory pattern is:

<path_to_where_you_want>/<ll_CC>/LC_MESSAGES/

Portable Object files

PO files are plain text files that contain your translation. You can safely edit them by hand.

po minimalistic example (en_US/LC_MESSAGES/mydomain.po):

msgid ""
msgstr ""
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"

msgid "Simple test"
msgstr "A small sentence in english"

Once edited, each PO file must be indexed using:

msgfmt mydomain.po -o mydomain.mo

This command won't work if you don't have gettext™ tools installed on your system.

This will produce a MO file (machine object) indexing your translation for quick access.

Then you have to translate this file in other languages.

po minimalistic example (fr_FR/LC_MESSAGES/mydomain.po):

msgid ""
msgstr ""
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"

msgid "Simple test"
msgstr "Une petite phrase en français"

The translation file must also be indexed:

msgfmt mydomain.po -o mydomain.mo

Translation Domain

The domain is matched against your translation file names. In above examples we used 'mydomain' as domain name.

You can have more than one domain for the same application, it can enhance gettext™'s performance to split your application translations in more than one file.

Using Translator in PHP

<?php
require_once 'PHPTAL.php';
require_once 'PHPTAL/GetTextTranslator.php';

try {
    $tr = new PHPTAL_GetTextTranslator();

    // set language to use for this session (first valid language will
    // be used)
    $tr->setLanguage('en_GB.utf8', 'en_GB');

    // register gettext domain to use
    $tr->addDomain('mydomain', '/path/to/your/translation_root');

    // specify current domain
    $tr->useDomain('mydomain');

    $tpl = new PHPTAL('mytemplate.xhtml');

    // tell PHPTAL to use our translator
    $tpl->setTranslator($tr);

    // output translated template
    echo $tpl->execute();
}
catch (Exception $e){
    echo $e;
}

If you need to translate some other text, that is not in the template (e.g. plaintext e-mail message), you can reuse PHPTAL's translator:

$tr = $tpl->getTranslator();

$subject = $tr->translate("Registration information");

$tr->setVar("user",$username);
$message = $tr->translate("Dear ${user}, thanks for registering!");

mail($email, $subject, $message);

If you're using PHPTAL's standard gettext™ translator, you can use gettext() too.

Variable interpolation

The I18N namespace allows some variable interpolation in your translations.

# english
msgid "welcome"
msgstr "Welcome ${name} you have ${n} mails!"

# french
msgid "welcome"
msgstr "Bienvenue ${name} vous avez recu ${n} messages!"

A template can use this interpolation as follows:

<span i18n:translate="welcome">
  Welcome
  <span i18n:name="name" tal:replace="user/name"/>
  you currently have
  <span i18n:name="n" tal:replace="user/unreadeMails"/>
  unread messages!
</span>

Because i18n:translate contains a value 'welcome', the template data will be ignored and the message given by gettext™ will be used instead.

Creating custom expression modifiers

PHPTAL comes with some basic expression modifiers (not:, exists:, string:, php:, path:).

These modifiers are defined by ZPT specifications but PHPTALES can be extended with your own modifiers to manipulate strings, date, money numbers, objects, whatever…

The aim of a modifier is to return some PHP code that will be included in the template PHP source.

Modifiers are used at parse time. If you change the behaviour of a modifier, you'll have to delete generated PHP files and reparse all templates using it.

Please note that modifiers produce code, and mustn't echo data!

Any PHP function starting with "phptal_tales_" is usuable as a modifier.

Modifiers takes two arguments:

  • $src: the source string after the "modifier:" keyword

  • $nothrow: a boolean which determines whether exceptions may be thrown or not by phptal_path() resolution. This boolean must be propagated whenever you call another phptal_tales_* modifier from within your own modifier.

For example, in the following TAL template,

<span tal:replace="some-modifier: my/path/value"/>

The src argument will be "my/path/value", and the $nothrow boolean will be false, because tal:replace requires the path to be fully resolvable.

An expression like:

<span tal:replace="some-modifier: my/path/value | other/path"/>

Will use 2 modifiers:

  • some-modifier: with "my/path/value" as $src argument and $nothrow set to true because an alternative exists

  • path: with "other/path" as $src, and $nothrow set to false because in case the alternative is not found, tal:replace will be in trouble.

Remember, path: is the implicit modifier used when no other modifier is specified.

Modifiers can use other modifiers to generate simpler PHP code. The example below shows this.

//
// This modifier will return a money formated string (XXX.XX)
//
// usage:
//
//      money: path/to/my/amount
//
// this modifier uses phptal_tales() function to generate the
// PHP code that will return the value of the modifier argument.
//
// in the example:
//
//      money: path/to/my/amount
//
// the produced code will be something looking like:
//
//      sprintf("%01.2f", phptal_path($ctx->path, "to/my/amount"))
//
// This code will be included right into the template where needed.
//
// @param string $src
//      The expression string
// @param string $nothrow
//      A boolean indicating if exceptions may be throw by phptal_path if
//      the path does not exists.
// @return string
//      PHP code to include in the template
//
function phptal_tales_money( $src, $nothrow )
{
    // remove spaces we do not require here
    $src = trim($src);
    return 'sprintf("%01.2f", '.phptal_tales($src, $nothrow).')';
}

Appendix A. Note for system administrators

PHPTAL functions by generating PHP files from the template's logic, this means that it needs a directory to store those generated files so they can be parsed by the PHP interpreter.

By default PHPTAL will use the system's temp directory (via PHP's sys_get_temp_dir() function if available) or will try to guess where it should be, /tmp on Unix like systems and c:\windows\temp on Microsoft ones, to store the compiled templates. The default destination can be changed to your liking by calling setPhpCodeDestination() method with the appropriate path. Be it the system's temp directory or a custom one, it needs to have its permissions setup as to allow the PHP running process (the Apache user if using mod_php or the cgi/fastcgi user otherwise) to create and update files in that directory.

PHPTAL creates one file for each different template file and one file for each tag if using phptal:cache. It doesn't create separate files for macros (which are simply compiled as PHP functions inside the compiled template file). These files are automatically cleaned up once in a while, more specifically, each time a template is compiled there is random probability, controlled by setCachePurgeFrequency() method, which will just delete files older than set by setCacheLifetime() method.

Alternatively you can also schedule the deletion of old/unused files by running this from an Unix-like shell (e.g. in a cron job):

find /tmp/ -name tpl_\* \( -atime +1 -o -mtime +14 \) -delete

Appendix B. Useful links

  • ZPT Zope Page Template front page,

  • TAL the Template Attribute Language page,

  • METAL is the Macro Expansion of TAL,

  • TALES the TAL Expression Syntax.

Appendix C. Greetings

Big thanks goes to:

  • ZPT team, who made these useful specifications,

  • The PHPTAL community for their support, help and reports,

  • Jean-Michel Hiver, who 'forced' me to look at them,

  • Olivier Parisy, the first enthusiastic PHPTAL user and bug finder,


Place for the page title

PHPTAL Manual PHP Template Attribute Language Laurent Bedubourg Kornel Lesinski Dan Sheppard Anton Valeriyevich Andriyevskyy Revision History ---------------------------------------------------------------------- Table of Contents 1. Introduction 2. Why use PHPTAL 3. Installation 4. First example 5. Template Attribute Language 1. Attribute priority 2. TAL namespace 1. tal:define 2. tal:condition 3. tal:repeat 4. tal:omit-tag 5. tal:replace 6. tal:content 7. tal:attributes 1. Optional attributes 8. tal:on-error 3. METAL namespace 1. metal:define-macro 2. metal:use-macro 3. metal:define-slot 4. metal:fill-slot 4. I18N namespace 1. i18n:translate 2. i18n:attributes 3. i18n:name 4. XHTML in translations 5. PHPTAL namespace 1. phptal:debug 2. phptal:cache 1. Instant refreshing 2. Limitations: 3. phptal:tales 6. tal:block 7. PHPTALES 1. path: 2. Alternative PHP operator syntax 3. string: 4. php: 5. not: 6. exists: 7. default 8. structure 9. Expression chains 6. PHP Integration 1. Constants 2. Configuration methods 1. setOutputMode(mode) 2. setEncoding(encoding) 3. Other methods 3. class PHPTAL 4. interface PHPTAL_Filter 5. interface PHPTAL_Trigger 6. interface PHPTAL_TranslationService 1. method setLanguage(...) 2. method useDomain($domain) 3. method setVar($key,$value) 4. method translate($key) 5. method setEncoding($encoding) 7. Working with gettext 1. Creating the translation directory structure 2. Portable Object files 3. Translation Domain 4. Using Translator in PHP 5. Variable interpolation 8. Creating custom expression modifiers 7. A. Note for system administrators 8. B. Useful links 9. C. Greetings Introduction ---------------------------------------------------------------------- PHPTAL is an implementation of the excellent Zope Page Template (ZPT) system for PHP. PHPTAL supports TAL, METAL, I18N namespaces. PHPTALES is the equivalent of TALES, the Template Attribute Language Expression Syntax. It defines how XML attribute values are handled. As PHPTALES is similar to TALES, it should be easy to port python TAL templates into PHP ones (and vice versa). To be TAL compliant, PHPTAL implements XPath-like access to data. PHPTAL is freely distributed under the LGPL license, it is developed by Laurent Bedubourg and maintained by Kornel Lesinski. Why use PHPTAL ---------------------------------------------------------------------- XML/HTML templates exist to separate logic from presentation in web services. This separation brings more than one accompanying benefit. o better application design o easier task repartition o better maintainability o easy web skins Most template systems uses , <% %> or tags to find their sections. It allows easier template system development but doesn't really help template designers. TAL hides most of its logic in XML attributes, preserving syntax and strucutre of XHTML. This allows previewing of TAL templates in web browser (WYSIWYG editors, live previews) and doesn't break HTML syntax highlighting in programmers' editors. If you have already worked with a simple template system, then you must have encountered something looking like: <%loop myarray as myitem %> <%/loop%>
<% myitem %>
Well, with PHPTAL you now can write:
text replaced by the item value sample 1 sample 2 sample 3
The above code will render correctly with the sample text in normal web browser, so you can present it to your clients even if the code required to get 'myarray' values doesn't yet exist. Another big advantage of PHPTAL is that you benefit from more than 3 years of Zope community experience, documentation, examples, and help. PHPTAL relies on this community to provide its users a great deal of useful information. PHPTAL is designed to be as customizable as possible for advanced developers and performance-eating systems, but still be easy to use for beginners, with a comfortable and simple default behaviour (at least we tried :) Installation ---------------------------------------------------------------------- PHPTAL is released as a PEAR package (see pear.php.net). You can download the PHPTAL library on the PHPTAL website: phptal.org. You can install it using the PEAR utility: pear install http://phptal.org/latest.tar.gz Once installed, you can upgrade PHPTAL easily on each PHPTAL update using PEAR: pear upgrade http://phptal.org/latest.tar.gz If you do not use PEAR or do not have it installed on your system, you can still install PHPTAL by unzipping the downloaded archive. tar zxvf PHPTAL-X.X.X.tar.gz cp -r PHPTAL-X.X.X/PHPTAL* /path/to/your/lib/folder This will install the PHPTAL.php file and the associated PHPTAL folder in /path/to/your/lib/folder. First example ---------------------------------------------------------------------- To get a first impression of PHPTAL usage, a simple example is better than many words. Your template is a valid XML/HTML document (with a root element). Here's a file named 'my_template_file.xhtml'. Place for the page title

sample title

Name | Phone
person's name | person's phone
sample name | sample phone
sample name | sample phone
In PHP, you just have to include the PHPTAL library, and maybe configure a few variables to customize the template system. name = $name; $this->phone = $phone; } } // let's create an array of objects for test purpose $people = array(); $people[] = new Person("foo", "01-344-121-021"); $people[] = new Person("bar", "05-999-165-541"); $people[] = new Person("baz", "01-389-321-024"); $people[] = new Person("quz", "05-321-378-654"); // put some data into the template context $template->title = 'The title value'; $template->people = $people; // execute the template try { echo $template->execute(); } catch (Exception $e){ echo $e; } ?> If you execute the PHP script, you will obtain something similar to what follows. The title value

The title value

Name | Phone
foo | 01-344-121-021
bar | 05-999-165-541
baz | 01-389-321-024
quz | 05-321-378-654
PHPTAL doesn't care much about line breaks and indentation in files it reads and generates. If you want source code of generated HTML files to be pretty (with line breaks and perfect indentation), then you might need to postprocess it with HTML Tidy. Template Attribute Language ---------------------------------------------------------------------- Table of Contents 1. Attribute priority 2. TAL namespace 1. tal:define 2. tal:condition 3. tal:repeat 4. tal:omit-tag 5. tal:replace 6. tal:content 7. tal:attributes 1. Optional attributes 8. tal:on-error 3. METAL namespace 1. metal:define-macro 2. metal:use-macro 3. metal:define-slot 4. metal:fill-slot 4. I18N namespace 1. i18n:translate 2. i18n:attributes 3. i18n:name 4. XHTML in translations 5. PHPTAL namespace 1. phptal:debug 2. phptal:cache 1. Instant refreshing 2. Limitations: 3. phptal:tales 6. tal:block 7. PHPTALES 1. path: 2. Alternative PHP operator syntax 3. string: 4. php: 5. not: 6. exists: 7. default 8. structure 9. Expression chains This section describes TAL and its extensions. It mainly targets template designers but must be read by PHP integrators as well. Attribute priority It is important to note that the order of declaration of attributes is irrelevant. For example, ... Is exactly the same as: ... Priority is the same as described by the TAL specification: 1. define 2. condition 3. repeat 4. content or replace 5. attributes 6. omit-tag TAL namespace 1. tal:define 2. tal:condition 3. tal:repeat 4. tal:omit-tag 5. tal:replace 6. tal:content 7. tal:attributes 1. Optional attributes 8. tal:on-error tal:define Defines variables in the template. It takes one or multiple semicolon-separated variable definitions. Making a shortcut to a long path:
...
Defining more than one variable at the same time: ... Each definition may start with global keyword which makes variable available everywhere later in the template and all macros. Global variables can be redefined.

On the contrary, a local variable is only available inside the element it is defined in (and inside marcos that are called in this element):

Tip You may also use tal:define with other attributes, it will be executed before any other attributes on the same element. Creating a string inside the template: Defining a string containing another variable: A small trick which uses content of the element (useful if you need to define very complex value): Hello ${fname}! Welcome to this page In above example, the tag won't show up because it has no printable content (hello variable grabs it) nor attributes. Note This is a special case. It only works if you use the global keyword. tal:condition The element and its content will be shown only if the condition is evaluated to true.

Welcome member ...

Please login before accessing this page

If the PHP backend does not provide your templates with enough methods, you will often have to fall back to PHP for special conditions: ... This may put too much logic inside the template and it is sometimes preferable to provide boolean attributes or accessible methods to the template: ... tal:repeat This attribute handles iterable objects like arrays, associative arrays, and objects implementing the PHP5 Iterator class. The repeat attribute repeats its element and its content until the end of the specified resource. text replaced by item Within a loop, you can access the current loop information (and that of its parent for nested loops) using specific repeat/* paths. In the above example: o repeat/item/key : returns the item's key if some/result is an associative resource (index otherwise) o repeat/item/index : returns the item index (0 to count-1) o repeat/item/number : returns the item number (1 to count) o repeat/item/even : returns true if item index is even o repeat/item/odd : returns true if item index is odd o repeat/item/start : returns true if item is the first one o repeat/item/end : returns true if item is the last one o repeat/item/length : returns the number of elements in some/result "item" depends on the receiver variable defined in tal:repeat expression. The most common usage of tal:repeat is in using some SQL database result. The following code will work if playersRanking contains object that implements PHP's Iterator interface:
Position | Player | Score
tal:omit-tag This attribute asks the PHPTAL parser to ignore the elements's open and close tag, its content will still be evaluated. if the condition is true, then only this text will appear and span open and close will be removed Will produce: only this text will appear, span open and close will be removed This attribute is useful when you want to create element optionally, e.g. hide a link if certain condition is met. If you want element that is never output, you can use tal:block only this text will appear, ten times. tal:replace This attribute will replace the entire tag with a value, or by nothing if no value is given. this ugly string and span Will produce: this beautiful string tal:replace can also be used to create samples in source templates, but remove them from final output.
item value
sample 1
sample 2
tal:content This attribute replaces the tag content with the evaluation of its expression. will be replaced Will produce: my string tal:attributes This attribute changes tag attribute(s) value(s). sample link With a 'somelink' having: $somelink->href = "http://www.google.com"; $somelink->title = "google search engine"; $somelink->text = "the google search engine"; Will produce: the google search engine Semicolon (;) separates attributes. If you want semicolon to be output in an attribute, you have to double it (;;). A somewhat complicated example involving tal:repeat: ... The php: modifier will be explained later, basically if the line is odd then tr will have a class attribute with "odd" as value, otherwise, no class will be set. The "condition ? then : else" is a regular PHP expression which must be used with care but has proven to be useful on more than one occasion. A better way to achieve the same result would be to ask your PHP coder to create a custom modifier for your needs (see PHP integration / custom modifiers) which would be used as follows: ... The modifier would return "odd" if repeat/ranking/odd is true, false otherwise. Optional attributes If you use TALES alternatives in tal:attributes and use nothing (or NULL in PHP) as last alternative, attribute won't be added at all if there's no value for it (this avoids adding empty attributes): ... tal:attributes="title object/tooltip | nothing"> XHTML attributes like selected, checked, etc. are properly handled automatically. Warning Remember that XHTML is case-sensitive, so SELECTED attribute is an error in XHTML. Use selected. tal:on-error This attribute replaces the tag by the tal:on-error expression evaluation if a path error is detected in the tag content, or if any PHP exception is thrown in the tag content. the user name here If an error occurs accessing 'name' or 'user', the error string will be shown at the tag's place. This also works on more than one level of template: METAL namespace 1. metal:define-macro 2. metal:use-macro 3. metal:define-slot 4. metal:fill-slot METAL stands for 'Macro Extension for TAL'. This namespace, supported by PHPTAL, allows template designers to define and call XML/XHTML macros. metal:define-macro This attribute declares a macro. Think of macros as library of small templates which can be reused in any other template.
  • home
  • products
  • contact
Last modified: page modification date
Macros inherit from the caller's dictionary. In the above example, the variable 'mdate' depends on the template that calls the macro. metal:use-macro This attribute calls a macro and includes its result in the current template. You can refer to external macros defined in other templates by specifying the template source file. It is interesting to note that you can also use the PHPTAL inline replacement feature inside the use-macro attribute value: Macro can call itself. This way you can output arrays recursively:
metal:define-slot This attribute must appear inside a metal:define-macro tag. Slots can be replaced by caller template with some custom dynamically-generated XML/XHTML. Slots can be thought of like reverse includes, a macro can be an entire page and slots customize this page depending on the URL. For instance, a slot may contain the latest news in the home page or user actions when the member is logged in.
news description
The above example defines a place called 'news_place' which can be overwritten by caller templates. See next section for the continuation of this example. metal:fill-slot This attribute can occur only inside metal:use-macro element. This explicitly tells PHPTAL to replace a defined slot with the content provided inside the metal:fill-slot attribute.

user menu

  • inbox
  • new mail
  • disconnect
 Slots give the opportunity to define really customizable and reusable page templates with a simple push technology. I18N namespace 1. i18n:translate 2. i18n:attributes 3. i18n:name 4. XHTML in translations Note i18n is a short name for 'internationalization'. This namespace allow template designers to specify some text zones that must be translated during template evaluation. i18n:translate This attribute defines some text part that must be translated using PHPTAL's translation system.
Welcome here
In the above example, PHPTAL will looks for a translation key named 'welcome_message' and will replace the content of the tag with the equivalent in currently requested language.
Welcome here
This usage is a little different, no translation key is given, thus PHPTAL will use the content of the tag 'Welcome here' as the translation key. This is a regular translation if translation system knows the key 'Welcome here'. If no translation is found, the key will be used as the translation result. That's why using readable message instead of keys may be a good choice. Please note that the key to translate may be contained in a variable, to allow dynamic key selection.
...
i18n:attributes Defines which attributes should be translated. Takes semicolon-separated list of attributes and keys similar to those for i18n:translate. i18n:name This attribute sets a translation variable value. Translations may contain ${xxx} strings where "xxx" is the name of a variable that needs to be interpolated dynamically. The value of this variable will be set to the tag and its content. If you don't need tag around the value, use tal:replace instead of tal:content. tal:omit-tag may help if the value is a concatenation of strings. foo foo An example of i18n usage:
Welcome , you have unread mails.
The translation key of this example will be: "Welcome ${user}, you have ${mails} unread mails." PHPTAL will replace ${user} with ${user/name} and ${mails} with ${user/nbrMails} in translation. More information about I18N with PHPTAL is available in the PHP section of this book. XHTML in translations By defaults translations are assumed to contain only text, so PHPTAL escapes all "<" characters. You can use structure keyword in i18n:translate to disable escaping and use translated text as-is:
Gives:
bold text
Warning Caveats: This will only work in simplest cases - TAL attributes inside translated strings are ignored. Ill-formed XHTML in translations will break page well-formedness. PHPTAL namespace 1. phptal:debug 2. phptal:cache 1. Instant refreshing 2. Limitations: 3. phptal:tales These attributes are not defined in TAL specifications, but are useful when working with PHPTAL. phptal:debug This attribute toggles the activation of PHPTAL debugging for the content of the tag it is defined in. Note To debug errors in macros called across templates you need to add phptal:debug in template which defines the macro, not the one which uses it. The debug mode stores information like filename and source line number in the template, so exceptions thrown by incorrect path access will contain more information about where they where thrown. ...
...
...
phptal:cache This attribute causes output of entire element (including its tag) to be cached on disk and not re-evaluated until cache expires. Note Use of cache is beneficial only for elements that use very complex expressions, macros from external files or PHP expressions/objects that access the database. Otherwise uncached templates will be just as fast. Content of this attribute is a duration (how long element should be kept in cache) written as number with 'd', 'h', 'm' or 's' suffix.
...
will be evaluated at most once per 3 hours. Duration can be followed by optional "per" parameter that defines how cache should be shared. By default cache is shared between all pages that use that template. You can add "per url" to have separate copy of given element for every URL.
    ...
    will be cached for one day, separately for each page. You can add "per expression" to have different cache copy for every different value of an expression (which MUST evaluate to a string). Expression cannot refer to variables defined using tal:define on the same element.
      ...
      will be cached for 25 minutes, separately for each object ID. Instant refreshing Instead of clearing cache, it might be a better idea to put version or last modification timestamp in the per parameter. This will cause cached template to be refreshed as soon as version/timestamp changes and no special cache clearing will be neccessary.
      ...
      Limitations: o phptal:cache blocks can be nested, but outmost block will cache other blocks regardless of their freshness. o You cannot use metal:fill-slot inside elements with phptal:cache. o phptal:tales This attribute allows us to change the behaviour of PHPTALES. The default behaviours is to interpret attribute expressions in a very ZPT way. But sometimes you just would like to have PHP there, and you end up using php: modifier everywhere. Another problem concerning PHPTALES is the way PHPTAL has to interpret paths. For example, myobject/mymethod/property/10/othermethod/hashkey takes relatively long to interpret (but don't worry about this too much - don't optimize until you find that it is really a problem with performance!) PHPTAL has (at runtime) to take myobject and discover that it is an object; find out that 'mymethod' is a method of this object (rather than a variable), and then to call it; explore the result to determine that it is an object with a property; find that its value is an array; find the 'ten' element of this array, and determine that it is an object; decide that othermethod is a method of this object (rather than a variable), and get the result of its execution; find that it is an object, and then retrieve the value for the key 'hashkey'. Of course this was an extreme example and most of the time we don't care, because the process is fast enough. But what if this very long path is called inside a big tal:repeat? D'oh! phptal:tales can help us here:
      Please note that the above example does the same as:
      Note php: modifier is explained in its own chapter. tal:block tal:block is a syntactic sugar for elements which contains many TAL attributes which are not to be echoed. is the same as: Another example:
      is the same as:
      PHPTALES 1. path: 2. Alternative PHP operator syntax 3. string: 4. php: 5. not: 6. exists: 7. default 8. structure 9. Expression chains PHPTALES is the expression syntax used inside tal, metal, PHPTAL attributes. From above examples, you should have seen some PHPTALES examples (string:, php:, not:, ...). This chapter describes the usage of PHPTALES in templates. The value of a TAL attribute may contain more than one expression (ex: tal:define), in which case each expression must be separated from the next one with a ';' character. path: This is the default modifier used in TAL expression when no other modifier is specified. The following lines will give the same result: ${data/user/name} Inside the template or inside expression strings, you can refer to a context variable using its path in the form ${path/to/my/variable}

      ${document/title}

      Alternative PHP operator syntax Because '<', '>' and '&' characters are cumbersome to use in XML, PHPTAL provides alternative syntax for PHP operators using these characters, and a few more for consistency. These operators can be used only in php: expressions. o < : LT (less than) o > : GT (greater than) o <= : LE (less or equal) o >= : GE (greater or equal) o == : EQ (equal) o != : NE (not equal) o && : AND o || : OR string: Because expressions are separated by a ';' character, and because '$' marks the start of a path, you must use: o ';;' when you want to insert a real ';' character in a string, o '$$' when you want to insert a real '$' character in a string. string:foo $bar baz string:foo $$bar baz string:foo ; php:doFoo() string:foo ;; php:doFoo() php: This expression evaluates what follows as a regular PHP expression except that '->' is replaced by dots '.' and variable names does are prefixed with a dollar '$' sign. A dot '.' separated from the rest of expression by spaces is assumed to be a concatenation sign. php:htmlentities(foo) php:'string ${varReplaced}' php:'string ${some.path().to[0].var}' php:NOT foo OR (bar GT baz) php:a + b php:array('a', 'b', 'c') php:range(0, 90) php:foo . a.b.c(e) . htmlentities(SomeClass::staticMethod()) php:SomeClass::ConstOfClass php:SomeClass::$staticVar php: should be used with care and won't be needed in 80% of your templates but sometimes you will need to invoke some special PHP method to be certain whether a user is logged in, or to retrieve specific complex data depending on some conditions, dynamically inside the template. not: This expression is a boolean one, useful in tal:condition statements. not logged exists: This expression returns true if the path specified after it exists, and false otherwise. It is analogous to PHP's isset(). Normally using a path which doesn't exist throws an error like "Cannot find variable 'foo' in current scope". Thus, uncertain paths must be checked first: Use user/preferences here if defined default This is not an expression but a keyword, allowing template designers to keep the content of a tag as an alternative value if an error occurs, or if something is not defined. default my var value no some/var and no other/path found here Unknown page Above examples introduce the '|' character that allows the definition of alternatives for defines or prints. structure This is not an expression modifier but a keyword. While printing variables inside PHPTAL templates, you will have noticed that PHPTAL encodes each variable to ensure the validity of the output document. Sometimes, you may use HTML/XML variables which must be echoed as is.

      In above examples, we assume that $document->title and $document->content are variables containing preformated HTML which must be echoed as is. Expression chains An expression chain is a list of expressions separated by '|' characters. While evaluating expressions separated by '|', PHPTAL will stop its evaluation when an expression value is not null and no error was raised while evaluating the expression. As a string: expression is always true, string: always terminates an expression chain whatever expression may follow. You can use php: expressions inside expression chains, like any other expression.

      PHP Integration ---------------------------------------------------------------------- Table of Contents 1. Constants 2. Configuration methods 1. setOutputMode(mode) 2. setEncoding(encoding) 3. Other methods 3. class PHPTAL 4. interface PHPTAL_Filter 5. interface PHPTAL_Trigger 6. interface PHPTAL_TranslationService 1. method setLanguage(...) 2. method useDomain($domain) 3. method setVar($key,$value) 4. method translate($key) 5. method setEncoding($encoding) 7. Working with gettext 1. Creating the translation directory structure 2. Portable Object files 3. Translation Domain 4. Using Translator in PHP 5. Variable interpolation 8. Creating custom expression modifiers This section is aimed at PHP developers and explains how to use and customize PHPTAL behaviours for simple and advanced usage. o PHPTAL: the main PHPTAL class. It is used to load and execute templates. o PHPTAL_Filter: filtering template sources and PHPTAL output. o PHPTAL_Trigger: handles output of elements with phptal:id. o PHPTAL_TranslationService: for replacing the built-in gettext support with your own internationalization system. Constants The only constant defined in PHPTAL.php is PHPTAL_VERSION. It contains version of PHPTAL library installed on your system (in format: X.X.X). In older versions of there were constants for configuration. They have been removed in favour of methods. Configuration methods 1. setOutputMode(mode) 2. setEncoding(encoding) 3. Other methods PHPTAL tries to use best defaults possible and you shouldn't need to change any of the settings. All of these are methods of the PHPTAL class. set* methods return instance of their class, so you can chain them: setPhpCodeDestination('/tmp/phptal')->setOutputMode(PHPTAL::XML)->setTemplate('tpl.zpt')->execute(); ?> is the same as: setPhpCodeDestination('/tmp/phptal'); $phptal->setOutputMode(PHPTAL::XML); $phptal->setTemplate('tpl.zpt'); echo $phptal->execute(); ?> There are other set* methods for filters, internationalisation, etc. They have been described in other sections of this manual. setOutputMode(mode) Changes what syntax is used when generating elements. Valid modes: PHPTAL::XHTML In this mode (which is default) PHPTAL will output XHTML in a way that is backwards-compatible with HTML browsers. o Empty elements will be forced to use self-closing form ( , ), and non-empty elements will always have closing tag. Warning XHTML output mode changes element in way that is incompatible with RSS. Use XML output mode to generate RSS feeds or use Atom. o Boolean attribtes (checked, selected, etc.) will always have value required by the XHTML specification (it simplifies use of tal:attributes). o . Namespace declarations, name prefixes, explicit CDATA sections and other HTML-incompatible constructs will be ommited. Note This mode is not a "tag soup". PHPTAL will close all elements properly and quote attributes when it's necesary. Output will be properly formatted HTML 5, and fully backwards-compatible with current HTML 4 browsers. PHPTAL::XML This mode outputs "pure" XML without compatibility with text/html parsing. Use this mode when generating feeds, SVG, MathML, RDF and other XML files. setEncoding(encoding) Specify charcter encoding used by your templates. The default is UTF-8. PHPTAL assumes that encoding of all templates and generated documents is the same. BOM (Byte Order Marker) is removed from UTF-8 documents. Note PHPTAL does not read encoding from XML files and never converts character encodings. Tip Save yourself trouble and always use UTF-8 for everything. Other methods setTemplateRepository(string_or_array) Specifies where to look for templates. If given a string, it adds it to the list of paths searched. If given array, it replaces the list. This doesn't mean all your files need to be in the root directory, you can use sub folders to organize your template designer's work. It's just a shortcut which will allow you to reference templates without specifying the real path, but instead their relative path within the repository. Tip It's like include_path, but for PHPTAL templates only. setPhpCodeDestination(path) To tell PHPTAL where to store its intermediate (temporary) PHP files. By default it uses directory given by PHP's sys_get_tmp_dir(), which usually is '/tmp/' directory. setPhpCodeExtension(string) What filename extension should be used for intermediate PHP files. The default is php and frankly, there's no reason to change it. setCacheLifetime(num_days) Maximum number of days intermediate files and fragments cached with phptal:cache should be kept. setForceReparse(boolean) Forces reparsing of all templates all the time. It should be used only for testing and debugging. It's useful if you're testing prefilters or changing code of PHPTAL itself. Warning This slows down PHPTAL very much. Never enable this on production servers! class PHPTAL This is the main library class for you to use. The most common method of use: title = 'my title'; $tpl->values = array(1,2,3,4); $tpl->user = new User('Joe'); // execute the template and echo the result in a 'secure' way try { echo $tpl->execute(); } catch (Exception $e){ echo "Exception thrown while processing template\n"; echo $e; } ?> You can perfectly well choose to specify the template source after setting context variables. set('title', 'my title'); $tpl->set('values', array(1,2,3,4)); $tpl->set('user', new User('Joe')); $tpl->setTemplate('mytemplate.xhtml'); ... ?> You can also decide to use a generated string as the template source instead of using an existing template file: my title

      my title

      EOS; require_once 'PHPTAL.php'; $tpl = new PHPTAL(); $tpl->setSource($src); $tpl->title = 'this is my title'; try { echo $tpl->execute(); } catch (Exception $e){ echo $e; } ?> In the above example, because PHPTAL requires a template source identifier (usually the template file realpath), PHPTAL will use the md5 of the $src parameter as a unique identifier. You may decide to force the identifier using a second setSource() argument: my title

      my title

      EOS; require_once 'PHPTAL.php'; $tpl = new PHPTAL(); // If you specify where the source comes from (second argument to setSource), // PHPTAL will be able to generate more helpful error messages. $tpl->setSource($src, __FILE__); $tpl->title = 'this is my title'; try { echo $tpl->execute(); } catch (Exception $e){ echo $e; } ?> interface PHPTAL_Filter This interface allows you to automatically filter templates sources (pre-filters) or PHPTAL result (post-filters). Pre filters are invoked before the template parsing and won't be invoked until the source template file is modified. Post filters are invoked after each template execution. setPreFilter(new MyPreFilter()); $tpl->setPostFilter(new MyPostFilter()); echo $tpl->execute(); ?> You can set only one pre-Filter and one post-Filter using set*Filter. If you have more than one filter to chain, you can wrap them into a single class, implementing the PHPTAL_Filter interface, which would invoke the filter's chain. _filters[] = $filter; } public function filter($source){ foreach($this->_filters as $filter){ $source = $filter->filter($source); } return $source; } } $myfilter = new FilterChain(); $myfilter->add(new CommentFilter()); // imaginary filter $myfilter->add(new TidyFilter()); // imaginary filter $tpl = new PHPTAL('mytemplate.xhtml'); $tpl->setPostFilter($myFilter); echo $tpl->execute(); ?> interface PHPTAL_Trigger The phptal:id attribute was added into the PHPTAL for the PHP5 version to replace the old PHPTAL_Cache interface and to abstract it a little more. When a phptal:id is reached, PHPTAL will look in its triggers list for a matching id and will invoke the trigger start() and end() methods before entering the element, and just after it. If the PHPTAL_Trigger::start() methods returns PHPTAL_Trigger::SKIPTAG, PHPTAL will ignore the element and its content (start() may echo something to replace it). If your trigger wants the element and its content to be executed, you'll have to return PHPTAL_Trigger::PROCEED. The PHPTAL_Trigger::end() will be called after the element (whether it has been executed or not). This allows you to build cache systems using ob_start() in start() and ob_get_contents(), ob_end_clean() in end(). ...
      ... foo bar baz foo bar baz ...
      ... For some reason we decide the
      block requires to be cached. We introduce a phptal:id into the template: ...
      ... foo bar baz foo bar baz ...
      ... Then we write our trigger which will cache the
      content: _cachePath = 'cache.' . $tpl->getContext()->id; // if already cached, read the cache and tell PHPTAL to // ignore the tag content if (file_exists($this->_cachePath)){ $this->_usedCache = true; readfile($this->_cachePath); return self::SKIPTAG; } // no cache found, we start an output buffer and tell // PHPTAL to proceed (ie: execute the tag content) $this->_usedCache = false; ob_start(); return self::PROCEED; } // Invoked after tag execution public function end($phptalid, $tpl) { // end of tag, if cached file used, do nothing if ($this->_usedCache){ return; } // otherwise, get the content of the output buffer // and write it into the cache file for later usage $content = ob_get_contents(); ob_end_clean(); echo $content; $f = fopen($this->_cachePath, 'w'); fwrite($f, $content); fclose($f); } private $_cachePath; private $_usedCache; } ?> The key here is to return from start() with either SKIPTAG or PROCEED. When SKIPTAG is returned, PHPTAL will just ignore the tag and call end(). This usually means that the trigger takes the hand in deciding what to show there. When PROCEED is returned, PHPTAL will execute the tag and its content as usual, then call end(). This allows our cache class to play with output buffers to execute the tag once and to store the result in a file which will be used in later calls. To install our trigger we use: addTrigger('somePossiblyUniqueKeyword', $trigger); $tpl->id = 1; echo $tpl->execute(); ?> You can add as many triggers as you like to your templates. A generic cache trigger may also handle more than one phptal:id... etc... interface PHPTAL_TranslationService 1. method setLanguage(...) 2. method useDomain($domain) 3. method setVar($key,$value) 4. method translate($key) 5. method setEncoding($encoding) PHPTAL comes with a default gettext translation service, as shown in another section. For some reason you may prefer to implement your own service of translation. The PHPTAL_TranslationService interface is here to serve your needs. The usage of your service will be the same as the PHPTAL_GetTextTranslator. $tpl->setTranslator($yourOwnTranslatorInstance); Your implementation must define the following methods: method setLanguage(...) This method may be called by the template to change the current output language. Its arguments are a list of possible languages (use func_get_args() to get the argument array). The first known language should be used by your service. _currentLang = $lang; return; } } ... private $_currentLang; } ?> method useDomain($domain) If you decided to store your translations into separate files, one for each application, for example, this method allows you to select the translation domain from your templates (i18n:domain). _domains)){ $file = "domains/$this->_currentLang/$domain.php"; $this->_domains[$domain] = include($file); } $this->_currentDomain = $this->_domains[$domain]; } ... private $_currentDomain; private $_domains = array(); } ?> The above example is a possible translation solution where keys are stored in PHP files which return an associative array of key => translation. method setVar($key,$value) This method matches i18n:name calls. It builds an interpolation context for later translate calls. _context[$key] = $value; } ... private $_context = array(); } ?> method translate($key) The last and most important method to implement, it asks your service to translate the specified key for the currently selected language. _currentDomain[$key]; // interpolate ${myvar} using context associative array while (preg_match('/\${(.*?)\}/sm', $value, $m)){ list($src,$var) = $m; if (!array_key_exists($var, $this->_context)){ $err = sprintf('Interpolation error, var "%s" not set', $var); throw new Exception($err); } $value = str_replace($src, $this->_context[$var], $value); } return $value; } ... } ?> method setEncoding($encoding) PHPTAL class calls this method to inform your translation service what encoding is used by the template. translate() method should return strings in that encoding. If you always use the same encoding for templates and translation files (i.e. UTF-8), you can leave this method empty. Working with gettext 1. Creating the translation directory structure 2. Portable Object files 3. Translation Domain 4. Using Translator in PHP 5. Variable interpolation gettext is a standard GNU internationalization / translation system which can be used with PHP and which is supported by PHPTAL. The usage of gettext is simple but you will have to perform some tests to be sure everything works fine on your system. First, PHP must be compiled with the --with-gettext flag. See PHP documentation for how to do this. You can test your installation using following peace of code: // // test if gettext extension is installed with php // if (!function_exists("gettext")) { echo "gettext is not installed\n"; } else { echo "gettext is supported\n"; } Creating the translation directory structure The PHP gettext extension requires a specific structure which will contain your translation files. /path/to/your/translation_root/en_US/LC_MESSAGES/ /path/to/your/translation_root/en_GB/LC_MESSAGES/ /path/to/your/translation_root/fr_FR/LC_MESSAGES/ /path/to/your/translation_root/es_ES/LC_MESSAGES/ ... and so on ... The language code is composed of two characters defining the language itself (en, fr, es, ...) and two characters defining the country (US, GB, FR, ES, ...). The directory pattern is: //LC_MESSAGES/ Portable Object files PO files are plain text files that contain your translation. You can safely edit them by hand. po minimalistic example (en_US/LC_MESSAGES/mydomain.po): msgid "" msgstr "" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" msgid "Simple test" msgstr "A small sentence in english" Once edited, each PO file must be indexed using: msgfmt mydomain.po -o mydomain.mo This command won't work if you don't have gettext tools installed on your system. This will produce a MO file (machine object) indexing your translation for quick access. Then you have to translate this file in other languages. po minimalistic example (fr_FR/LC_MESSAGES/mydomain.po): msgid "" msgstr "" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" msgid "Simple test" msgstr "Une petite phrase en franc,ais" The translation file must also be indexed: msgfmt mydomain.po -o mydomain.mo Translation Domain The domain is matched against your translation file names. In above examples we used 'mydomain' as domain name. You can have more than one domain for the same application, it can enhance gettext's performance to split your application translations in more than one file. Using Translator in PHP setLanguage('en_GB.utf8', 'en_GB'); // register gettext domain to use $tr->addDomain('mydomain', '/path/to/your/translation_root'); // specify current domain $tr->useDomain('mydomain'); $tpl = new PHPTAL('mytemplate.xhtml'); // tell PHPTAL to use our translator $tpl->setTranslator($tr); // output translated template echo $tpl->execute(); } catch (Exception $e){ echo $e; } If you need to translate some other text, that is not in the template (e.g. plaintext e-mail message), you can reuse PHPTAL's translator: $tr = $tpl->getTranslator(); $subject = $tr->translate("Registration information"); $tr->setVar("user",$username); $message = $tr->translate("Dear ${user}, thanks for registering!"); mail($email, $subject, $message); If you're using PHPTAL's standard gettext translator, you can use gettext() too. Variable interpolation The I18N namespace allows some variable interpolation in your translations. # english msgid "welcome" msgstr "Welcome ${name} you have ${n} mails!" # french msgid "welcome" msgstr "Bienvenue ${name} vous avez recu ${n} messages!" A template can use this interpolation as follows: Welcome you currently have unread messages! Because i18n:translate contains a value 'welcome', the template data will be ignored and the message given by gettext will be used instead. Creating custom expression modifiers PHPTAL comes with some basic expression modifiers (not:, exists:, string:, php:, path:). These modifiers are defined by ZPT specifications but PHPTALES can be extended with your own modifiers to manipulate strings, date, money numbers, objects, whatever... The aim of a modifier is to return some PHP code that will be included in the template PHP source. Modifiers are used at parse time. If you change the behaviour of a modifier, you'll have to delete generated PHP files and reparse all templates using it. Please note that modifiers produce code, and mustn't echo data! Any PHP function starting with "phptal_tales_" is usuable as a modifier. Modifiers takes two arguments: o $src: the source string after the "modifier:" keyword o $nothrow: a boolean which determines whether exceptions may be thrown or not by phptal_path() resolution. This boolean must be propagated whenever you call another phptal_tales_* modifier from within your own modifier. For example, in the following TAL template, The src argument will be "my/path/value", and the $nothrow boolean will be false, because tal:replace requires the path to be fully resolvable. An expression like: Will use 2 modifiers: o some-modifier: with "my/path/value" as $src argument and $nothrow set to true because an alternative exists o path: with "other/path" as $src, and $nothrow set to false because in case the alternative is not found, tal:replace will be in trouble. Remember, path: is the implicit modifier used when no other modifier is specified. Modifiers can use other modifiers to generate simpler PHP code. The example below shows this. // // This modifier will return a money formated string (XXX.XX) // // usage: // // money: path/to/my/amount // // this modifier uses phptal_tales() function to generate the // PHP code that will return the value of the modifier argument. // // in the example: // // money: path/to/my/amount // // the produced code will be something looking like: // // sprintf("%01.2f", phptal_path($ctx->path, "to/my/amount")) // // This code will be included right into the template where needed. // // @param string $src // The expression string // @param string $nothrow // A boolean indicating if exceptions may be throw by phptal_path if // the path does not exists. // @return string // PHP code to include in the template // function phptal_tales_money( $src, $nothrow ) { // remove spaces we do not require here $src = trim($src); return 'sprintf("%01.2f", '.phptal_tales($src, $nothrow).')'; } Appendix A. Note for system administrators PHPTAL functions by generating PHP files from the template's logic, this means that it needs a directory to store those generated files so they can be parsed by the PHP interpreter. By default PHPTAL will use the system's temp directory (via PHP's sys_get_temp_dir() function if available) or will try to guess where it should be, /tmp on Unix like systems and c:\windows\temp on Microsoft ones, to store the compiled templates. The default destination can be changed to your liking by calling setPhpCodeDestination() method with the appropriate path. Be it the system's temp directory or a custom one, it needs to have its permissions setup as to allow the PHP running process (the Apache user if using mod_php or the cgi/fastcgi user otherwise) to create and update files in that directory. PHPTAL creates one file for each different template file and one file for each tag if using phptal:cache. It doesn't create separate files for macros (which are simply compiled as PHP functions inside the compiled template file). These files are automatically cleaned up once in a while, more specifically, each time a template is compiled there is random probability, controlled by setCachePurgeFrequency() method, which will just delete files older than set by setCacheLifetime() method. Alternatively you can also schedule the deletion of old/unused files by running this from an Unix-like shell (e.g. in a cron job): find /tmp/ -name tpl_\* \( -atime +1 -o -mtime +14 \) -delete Appendix B. Useful links o ZPT Zope Page Template front page, o TAL the Template Attribute Language page, o METAL is the Macro Expansion of TAL, o TALES the TAL Expression Syntax. Appendix C. Greetings Big thanks goes to: o ZPT team, who made these useful specifications, o The PHPTAL community for their support, help and reports, o Jean-Michel Hiver, who 'forced' me to look at them, o Olivier Parisy, the first enthusiastic PHPTAL user and bug finder,


PHPTAL :: Template Attribute Language for PHP 5

  • News
  • Introduction
  • Download
  • Manuals
  • FAQ
  • Mailinglist

Page not found

Sorry, couldn't find “manual/en/revhistory.html” on this server.

Newsfeed | Contact | © 2005-2009 Motion-Twin, Aardvark Media Ltd.


Next

PHPTAL Manual

PHP Template Attribute Language

Laurent Bédubourg

Kornel Lesiński

Dan Sheppard

Anton Valeriyevich Andriyevskyy

Revision History

Table of Contents

  1. Introduction
  2. Why use PHPTAL
  3. Installation
  4. First example
  5. Template Attribute Language
    1. Attribute priority
    2. TAL namespace
      1. tal:define
      2. tal:condition
      3. tal:repeat
      4. tal:omit-tag
      5. tal:replace
      6. tal:content
      7. tal:attributes
        1. Optional attributes
      8. tal:on-error
    3. METAL namespace
      1. metal:define-macro
      2. metal:use-macro
      3. metal:define-slot
      4. metal:fill-slot
    4. I18N namespace
      1. i18n:translate
      2. i18n:attributes
      3. i18n:name
      4. XHTML in translations
    5. PHPTAL namespace
      1. phptal:debug
      2. phptal:cache
        1. Instant refreshing
        2. Limitations:
      3. phptal:tales
    6. tal:block
    7. PHPTALES
      1. path:
      2. Alternative PHP operator syntax
      3. string:
      4. php:
      5. not:
      6. exists:
      7. default
      8. structure
      9. Expression chains
  6. PHP Integration
    1. Constants
    2. Configuration methods
      1. setOutputMode(mode)
      2. setEncoding(encoding)
      3. Other methods
        1. setTemplateRepository(string_or_array)
        2. setPhpCodeDestination(path)
        3. setPhpCodeExtension(string)
        4. setCacheLifetime(num_days)
        5. setForceReparse(boolean)
    3. class PHPTAL
      1. echoExecute() method
        1. Limitations
    4. interface PHPTAL_Filter
    5. interface PHPTAL_Trigger
    6. interface PHPTAL_TranslationService
      1. method setLanguage(…)
      2. method useDomain($domain)
      3. method setVar($key,$value)
      4. method translate($key)
      5. method setEncoding($encoding)
    7. Working with gettext
      1. Creating the translation directory structure
      2. Portable Object files
      3. Translation Domain
      4. Using Translator in PHP
      5. Variable interpolation
    8. Creating custom expression modifiers
  7. A. Note for system administrators
  8. B. Useful links
  9. C. Greetings
Next
Introduction


Revision History
Revision v1.7 | 2009-06-06 | kl
Updates for PHPTAL 1.2.0
Revision v1.6 | 2008-10-03 | kl
Fixed errors spotted by Anton.
Revision v1.5 | 2008-08-21 | kl
Removed old defines, documented configuration methods.
Revision v1.4 | 2008-08-18 | kl
Corrections and updates for PHPTAL 1.1.13
Revision v1.3 | 2008-01-27 | kl
Updated for PHPTAL 1.1.10
Revision v1.2 | 2005-12-10 | ds
English Corrections by Dan Sheppard
Revision v1.1 | 2005-03-29 | lb
Added section about PHPTAL class
Revision v1.0 | 2005-03-27 | lb
Converted draft to docbook


PHPTAL Wiki :: Wiki Homepage

  • News
  • Introduction
  • Download
  • Manuals
  • FAQ
  • Mailinglist
  • Wiki
 PHPTAL Wiki ➭ Start

Wiki Homepage

This is incubator for PHPTAL documentation and ideas. Don't hesitate to share your code samples and tips, plugins, wrappers for 3rd party libraries/frameworks, etc.

You can edit all pages! Just press Edit this page button top in navigation bar. To create new page, [[link]] to it first.

  • QuickStart tutorial
  • Integration with popular PHP frameworks
  • Zope Page Templates - links and specifications from the original TAL implementation
  • Upgrading
  • Lint tool for checking template syntax

Planned features

  • Custom cache plugins
  • Advanced prefilters
start.txt · Last modified: 2009/09/23 11:22 by Kornel
Page History | What links here
All Recent changes (as feed) | Contact | © 2005-2009 Motion-Twin, Aardvark Media Ltd.
Except where otherwise noted, content on this wiki is licensed under the following license:GNU Free Documentation License 1.2


Page has moved

 Click here...


PHPTAL Wiki :: Custom cache

  • News
  • Introduction
  • Download
  • Manuals
  • FAQ
  • Mailinglist
  • Wiki
 PHPTAL Wiki ➭ You are here: Wiki Homepage ➭ Custom cache
Table of Contents
  • Custom cache
    • Problems
    • Desired features

Custom cache

This page contains design of future improvements to caching. Only basic syntax works in current releases.

Current syntax is:

 phptal:cache="<time> per url"

or

 phptal:cache="<time> per <expresssion>"

Where <time> is 1m, 1h, 1d, etc.

Problems

You can easily cache per URL and another variable (this requires definition of temporary variable and/or getting current URL passed to the template).

It could be solved by using

  phptal:cache="<time>;? per <url|expresssion> [; per <url|expression>]* "

e.g.

  phptal:cache="1h; per url; per user/id"

Desired features

PHPTAL needs cache "plugins" to be able to use APC, memcached and other caching mechanisms.

What should be interface of this class?

What information plugins need? Should they parse phptal:cache expression or only parsed and processed data?

cache.txt · Last modified: 2009/09/23 11:20 by Kornel
Page History | What links here
All Recent changes (as feed) | Contact | © 2005-2009 Motion-Twin, Aardvark Media Ltd.
Except where otherwise noted, content on this wiki is licensed under the following license:GNU Free Documentation License 1.2


PHPTAL Wiki :: Custom cache

  • News
  • Introduction
  • Download
  • Manuals
  • FAQ
  • Mailinglist
  • Wiki
 PHPTAL Wiki ➭ You are here: Wiki Homepage ➭ Custom cache

Old Revisions

These are the older revisons of the current document. To revert to an old revision, select it from below, click Edit this page and save it.

  • 2009/09/23 11:20 [image] cache – created Kornel (current)
cache.txt · Last modified: 2009/09/23 11:20 by Kornel
Page History | What links here
All Recent changes (as feed) | Contact | © 2005-2009 Motion-Twin, Aardvark Media Ltd.
Except where otherwise noted, content on this wiki is licensed under the following license:GNU Free Documentation License 1.2


PHPTAL Wiki :: Custom cache

  • News
  • Introduction
  • Download
  • Manuals
  • FAQ
  • Mailinglist
  • Wiki
 PHPTAL Wiki ➭ You are here: Wiki Homepage ➭ Custom cache

Edit the page and hit Save. See syntax for Wiki syntax. Please edit the page only if you can improve it. If you want to test some things, learn to make your first steps on the playground.

Media Files
Note: By editing this page you agree to license your content under the following license: GNU Free Documentation License 1.2
cache.txt · Last modified: 2009/09/23 11:20 by Kornel
Page History | What links here
All Recent changes (as feed) | Contact | © 2005-2009 Motion-Twin, Aardvark Media Ltd.
Except where otherwise noted, content on this wiki is licensed under the following license:GNU Free Documentation License 1.2


cache

Table of Contents
  • Custom cache
    • Problems
    • Desired features

Custom cache

This page contains design of future improvements to caching. Only basic syntax works in current releases.

Current syntax is:

 phptal:cache="<time> per url"

or

 phptal:cache="<time> per <expresssion>"

Where <time> is 1m, 1h, 1d, etc.

Problems

You can easily cache per URL and another variable (this requires definition of temporary variable and/or getting current URL passed to the template).

It could be solved by using

  phptal:cache="<time>;? per <url|expresssion> [; per <url|expression>]* "

e.g.

  phptal:cache="1h; per url; per user/id"

Desired features

PHPTAL needs cache "plugins" to be able to use APC, memcached and other caching mechanisms.

What should be interface of this class?

What information plugins need? Should they parse phptal:cache expression or only parsed and processed data?


PHPTAL Wiki :: Custom cache

  • News
  • Introduction
  • Download
  • Manuals
  • FAQ
  • Mailinglist
  • Wiki
 PHPTAL Wiki ➭ You are here: Wiki Homepage ➭ Custom cache

Recent Changes

The following pages were changed recently.

  • 2009/10/08 10:44 Show differences to current revisions Old revisions Upgrading from older releases – Kornel
  • 2009/10/04 01:06 Show differences to current revisions Old revisions Integrating with Frameworks – Kornel
  • 2009/09/23 11:26 Show differences to current revisions Old revisions Prefilters – Kornel
  • 2009/09/23 11:22 Show differences to current revisions Old revisions Wiki Homepage – Kornel
  • 2009/09/23 11:20 Show differences to current revisions Old revisions Custom cache – created Kornel
  • 2009/09/19 14:24 Show differences to current revisions Old revisions Quick Start – Kornel
  • 2009/09/19 03:04 Show differences to current revisions Old revisions Lint tool – Kornel
cache.txt · Last modified: 2009/09/23 11:20 by Kornel
Page History | What links here
All Recent changes (as feed) | Contact | © 2005-2009 Motion-Twin, Aardvark Media Ltd.
Except where otherwise noted, content on this wiki is licensed under the following license:GNU Free Documentation License 1.2


PHPTAL Wiki :: Custom cache

  • News
  • Introduction
  • Download
  • Manuals
  • FAQ
  • Mailinglist
  • Wiki
 PHPTAL Wiki ➭ You are here: Wiki Homepage ➭ Custom cache

Backlinks

This is a list of pages that seem to link back to the current page.

  • Wiki Homepage
cache.txt · Last modified: 2009/09/23 11:20 by Kornel
Page History | What links here
All Recent changes (as feed) | Contact | © 2005-2009 Motion-Twin, Aardvark Media Ltd.
Except where otherwise noted, content on this wiki is licensed under the following license:GNU Free Documentation License 1.2


PHPTAL Wiki :: Custom cache

  • News
  • Introduction
  • Download
  • Manuals
  • FAQ
  • Mailinglist
  • Wiki
 PHPTAL Wiki ➭ You are here: Wiki Homepage ➭ Custom cache

Index

This is an index over all available pages ordered by namespaces.

  • playground
  • wiki
  • Custom cache
  • Prefilters
  • Integrating with Frameworks
  • Lint tool
  • Quick Start
  • Wiki Homepage
  • Upgrading from older releases
  • Zope Page Templates
cache.txt · Last modified: 2009/09/23 11:20 by Kornel
Page History | What links here
All Recent changes (as feed) | Contact | © 2005-2009 Motion-Twin, Aardvark Media Ltd.
Except where otherwise noted, content on this wiki is licensed under the following license:GNU Free Documentation License 1.2


PHPTAL Wiki :: Prefilters

  • News
  • Introduction
  • Download
  • Manuals
  • FAQ
  • Mailinglist
  • Wiki
 PHPTAL Wiki ➭ You are here: Wiki Homepage ➭ Prefilters

Prefilters

Implementation is not finished yet! But have a look at the source of PHPTAL/PreFilter.php:

http://phptal.org/files/PHPTAL-1.2.1b3.tar.gz

There's base abstract class for prefilters. Previously you had to implement interface, now you'll have to extend the class. This change allows me to add new ways of filtering in the future without any breaking changes in the interface.

The class has methods like filterDOM($node), filter($source) — you just override which ones you want. You can override all of them at once if you need, all will be called.

DOM version lets you edit PHPTAL DOM nodes after they've been parsed and edit exactly what PHPTAL "sees".

There's also filterDOMFragment($node) method. I plan to add phptal:filter="name_of_the_filter" attribute, which will let you apply filters selectively, e.g. (this is not implemented yet)

 <ul phptal:filter="remove_whitespace">
  <li>IE hates newlines in lists</li>
 </ul>
 <script phptal:filter="minify_javascript">
  etc.
 </script>

I've replaced PHPTAL→setPreFilter($filter) with PHPTAL→addPreFilter ($filter, $name = null). Yes, this means you can have any number of filters without workarounds (finally! :)

I wonder if there should be separate method for adding named prefilters for use with phptal:filter only? (e.g. you might want to make JS minification prefilter available, but you don't want to minify entire file). Currently I expect this to be handled within filter, i.e. filter would implement filterDOMFragment() only, and have filterDOM() do nothing.

Is that easy to use? Powerful enough? What do you think?

Suggested improvements

link prototype

The API looks ok to me, just one thing, since it's not a runtime operation (in the sense that a php file is generated for the template), I think it'll be great if it used something along the lines of Zend_Loader_PluginLoader.

Which basically when setup with paths and class prefixes is able to find "plugins" in several folders. This would allow to have a set of default filters in PHPTAL distribution but override them and create new ones easily just by placing the class files in a directory, not needing to register them manually at runtime, which once the template is compiled, is of no use.

So – phptal:filter="remove_whitespace" – would automatically try to include and instantiate a class for that filter.

While – PHPTAL->addPreFilter("remove_whitespace") – would just store the name for when compiling the template and instantiate the class then.

filters.txt · Last modified: 2009/09/23 11:26 by Kornel
Page History | What links here
All Recent changes (as feed) | Contact | © 2005-2009 Motion-Twin, Aardvark Media Ltd.
Except where otherwise noted, content on this wiki is licensed under the following license:GNU Free Documentation License 1.2


PHPTAL Wiki :: Prefilters

  • News
  • Introduction
  • Download
  • Manuals
  • FAQ
  • Mailinglist
  • Wiki
 PHPTAL Wiki ➭ You are here: Wiki Homepage ➭ Prefilters

Old Revisions

These are the older revisons of the current document. To revert to an old revision, select it from below, click Edit this page and save it.

  • 2009/09/23 11:26 [image] filters – Kornel (current)
  • 2009/09/23 11:24 Show differences to current revisions filters – created Kornel
filters.txt · Last modified: 2009/09/23 11:26 by Kornel
Page History | What links here
All Recent changes (as feed) | Contact | © 2005-2009 Motion-Twin, Aardvark Media Ltd.
Except where otherwise noted, content on this wiki is licensed under the following license:GNU Free Documentation License 1.2


PHPTAL Wiki :: Prefilters

  • News
  • Introduction
  • Download
  • Manuals
  • FAQ
  • Mailinglist
  • Wiki
 PHPTAL Wiki ➭ You are here: Wiki Homepage ➭ Prefilters

Edit the page and hit Save. See syntax for Wiki syntax. Please edit the page only if you can improve it. If you want to test some things, learn to make your first steps on the playground.

Media Files
Note: By editing this page you agree to license your content under the following license: GNU Free Documentation License 1.2
filters.txt · Last modified: 2009/09/23 11:26 by Kornel
Page History | What links here
All Recent changes (as feed) | Contact | © 2005-2009 Motion-Twin, Aardvark Media Ltd.
Except where otherwise noted, content on this wiki is licensed under the following license:GNU Free Documentation License 1.2


filters

Prefilters

Implementation is not finished yet! But have a look at the source of PHPTAL/PreFilter.php:

http://phptal.org/files/PHPTAL-1.2.1b3.tar.gz

There's base abstract class for prefilters. Previously you had to implement interface, now you'll have to extend the class. This change allows me to add new ways of filtering in the future without any breaking changes in the interface.

The class has methods like filterDOM($node), filter($source) — you just override which ones you want. You can override all of them at once if you need, all will be called.

DOM version lets you edit PHPTAL DOM nodes after they've been parsed and edit exactly what PHPTAL "sees".

There's also filterDOMFragment($node) method. I plan to add phptal:filter="name_of_the_filter" attribute, which will let you apply filters selectively, e.g. (this is not implemented yet)

 <ul phptal:filter="remove_whitespace">
  <li>IE hates newlines in lists</li>
 </ul>
 <script phptal:filter="minify_javascript">
  etc.
 </script>

I've replaced PHPTAL→setPreFilter($filter) with PHPTAL→addPreFilter ($filter, $name = null). Yes, this means you can have any number of filters without workarounds (finally! :)

I wonder if there should be separate method for adding named prefilters for use with phptal:filter only? (e.g. you might want to make JS minification prefilter available, but you don't want to minify entire file). Currently I expect this to be handled within filter, i.e. filter would implement filterDOMFragment() only, and have filterDOM() do nothing.

Is that easy to use? Powerful enough? What do you think?

Suggested improvements

link prototype

The API looks ok to me, just one thing, since it's not a runtime operation (in the sense that a php file is generated for the template), I think it'll be great if it used something along the lines of Zend_Loader_PluginLoader.

Which basically when setup with paths and class prefixes is able to find "plugins" in several folders. This would allow to have a set of default filters in PHPTAL distribution but override them and create new ones easily just by placing the class files in a directory, not needing to register them manually at runtime, which once the template is compiled, is of no use.

So – phptal:filter="remove_whitespace" – would automatically try to include and instantiate a class for that filter.

While – PHPTAL->addPreFilter("remove_whitespace") – would just store the name for when compiling the template and instantiate the class then.


PHPTAL Wiki :: Prefilters

  • News
  • Introduction
  • Download
  • Manuals
  • FAQ
  • Mailinglist
  • Wiki
 PHPTAL Wiki ➭ You are here: Wiki Homepage ➭ Prefilters

Recent Changes

The following pages were changed recently.

  • 2009/10/08 10:44 Show differences to current revisions Old revisions Upgrading from older releases – Kornel
  • 2009/10/04 01:06 Show differences to current revisions Old revisions Integrating with Frameworks – Kornel
  • 2009/09/23 11:26 Show differences to current revisions Old revisions Prefilters – Kornel
  • 2009/09/23 11:22 Show differences to current revisions Old revisions Wiki Homepage – Kornel
  • 2009/09/23 11:20 Show differences to current revisions Old revisions Custom cache – created Kornel
  • 2009/09/19 14:24 Show differences to current revisions Old revisions Quick Start – Kornel
  • 2009/09/19 03:04 Show differences to current revisions Old revisions Lint tool – Kornel
filters.txt · Last modified: 2009/09/23 11:26 by Kornel
Page History | What links here
All Recent changes (as feed) | Contact | © 2005-2009 Motion-Twin, Aardvark Media Ltd.
Except where otherwise noted, content on this wiki is licensed under the following license:GNU Free Documentation License 1.2


PHPTAL Wiki :: Prefilters

  • News
  • Introduction
  • Download
  • Manuals
  • FAQ
  • Mailinglist
  • Wiki
 PHPTAL Wiki ➭ You are here: Wiki Homepage ➭ Prefilters

Backlinks

This is a list of pages that seem to link back to the current page.

  • Wiki Homepage
filters.txt · Last modified: 2009/09/23 11:26 by Kornel
Page History | What links here
All Recent changes (as feed) | Contact | © 2005-2009 Motion-Twin, Aardvark Media Ltd.
Except where otherwise noted, content on this wiki is licensed under the following license:GNU Free Documentation License 1.2


PHPTAL Wiki :: Prefilters

  • News
  • Introduction
  • Download
  • Manuals
  • FAQ
  • Mailinglist
  • Wiki
 PHPTAL Wiki ➭ You are here: Wiki Homepage ➭ Prefilters

Index

This is an index over all available pages ordered by namespaces.

  • playground
  • wiki
  • Custom cache
  • Prefilters
  • Integrating with Frameworks
  • Lint tool
  • Quick Start
  • Wiki Homepage
  • Upgrading from older releases
  • Zope Page Templates
filters.txt · Last modified: 2009/09/23 11:26 by Kornel
Page History | What links here
All Recent changes (as feed) | Contact | © 2005-2009 Motion-Twin, Aardvark Media Ltd.
Except where otherwise noted, content on this wiki is licensed under the following license:GNU Free Documentation License 1.2


PHPTAL Wiki :: Integrating with Frameworks

  • News
  • Introduction
  • Download
  • Manuals
  • FAQ
  • Mailinglist
  • Wiki
 PHPTAL Wiki ➭ You are here: Wiki Homepage ➭ Integrating with Frameworks
Table of Contents
  • Integrating with Frameworks
    • Zend Framework
    • CodeIgniter
    • Kohana
    • Symfony

Integrating with Frameworks

How to get PHPTAL working with popular frameworks. Please add instructions or link to "glue" code, not just the frameworks themselves.

Zend Framework

  • Zend Framework + PHPTAL tutorial with ready to use "glue" code.
  • Short tutorial with Zend View example

CodeIgniter

  • CodeIgniter - with some glue from ci-ext wrappers.
  • Example integration on CI forum

Kohana

  • Kohana - FIXME add detailed English description
  • Example in Japanese

Symfony

  • Symfony template renderers with PHPTAL as example.
frameworks.txt · Last modified: 2009/10/04 01:06 by Kornel
Page History | What links here
All Recent changes (as feed) | Contact | © 2005-2009 Motion-Twin, Aardvark Media Ltd.
Except where otherwise noted, content on this wiki is licensed under the following license:GNU Free Documentation License 1.2


PHPTAL Wiki :: Integrating with Frameworks

  • News
  • Introduction
  • Download
  • Manuals
  • FAQ
  • Mailinglist
  • Wiki
 PHPTAL Wiki ➭ You are here: Wiki Homepage ➭ Integrating with Frameworks

Old Revisions

These are the older revisons of the current document. To revert to an old revision, select it from below, click Edit this page and save it.

  • 2009/10/04 01:06 [image] frameworks – Kornel (current)
  • 2009/09/24 00:27 Show differences to current revisions frameworks – Kornel
  • 2009/09/22 17:04 Show differences to current revisions frameworks – Symfony Kornel
  • 2009/09/22 17:03 Show differences to current revisions frameworks – Kornel
  • 2009/09/19 02:51 Show differences to current revisions frameworks – Kornel
  • 2009/09/19 02:50 Show differences to current revisions frameworks – Kornel
  • 2009/09/19 02:02 Show differences to current revisions frameworks – ah, the link! :D Kornel
  • 2009/09/19 01:59 Show differences to current revisions frameworks – Kornel
  • 2009/09/18 18:21 Show differences to current revisions frameworks – 84.137.13.73
  • 2009/09/18 14:47 Show differences to current revisions frameworks – Kohana 83.10.12.173
  • 2009/09/17 23:18 Show differences to current revisions frameworks – 87.112.9.128
  • 2009/09/17 13:54 Show differences to current revisions frameworks – 84.137.0.228
  • 2009/09/17 13:42 Show differences to current revisions frameworks – Kornel
  • 2009/09/17 01:48 Show differences to current revisions frameworks – Kornel
  • 2009/09/17 01:47 Show differences to current revisions frameworks – Kornel
  • 2009/09/16 21:11 Show differences to current revisions frameworks – created 87.112.9.128
frameworks.txt · Last modified: 2009/10/04 01:06 by Kornel
Page History | What links here
All Recent changes (as feed) | Contact | © 2005-2009 Motion-Twin, Aardvark Media Ltd.
Except where otherwise noted, content on this wiki is licensed under the following license:GNU Free Documentation License 1.2


PHPTAL Wiki :: Integrating with Frameworks

  • News
  • Introduction
  • Download
  • Manuals
  • FAQ
  • Mailinglist
  • Wiki
 PHPTAL Wiki ➭ You are here: Wiki Homepage ➭ Integrating with Frameworks

Edit the page and hit Save. See syntax for Wiki syntax. Please edit the page only if you can improve it. If you want to test some things, learn to make your first steps on the playground.

Media Files
Note: By editing this page you agree to license your content under the following license: GNU Free Documentation License 1.2
frameworks.txt · Last modified: 2009/10/04 01:06 by Kornel
Page History | What links here
All Recent changes (as feed) | Contact | © 2005-2009 Motion-Twin, Aardvark Media Ltd.
Except where otherwise noted, content on this wiki is licensed under the following license:GNU Free Documentation License 1.2


frameworks

Table of Contents
  • Integrating with Frameworks
    • Zend Framework
    • CodeIgniter
    • Kohana
    • Symfony

Integrating with Frameworks

How to get PHPTAL working with popular frameworks. Please add instructions or link to "glue" code, not just the frameworks themselves.

Zend Framework

  • Zend Framework + PHPTAL tutorial with ready to use "glue" code.
  • Short tutorial with Zend View example

CodeIgniter

  • CodeIgniter - with some glue from ci-ext wrappers.
  • Example integration on CI forum

Kohana

  • Kohana - FIXME add detailed English description
  • Example in Japanese

Symfony

  • Symfony template renderers with PHPTAL as example.


PHPTAL Wiki :: Integrating with Frameworks

  • News
  • Introduction
  • Download
  • Manuals
  • FAQ
  • Mailinglist
  • Wiki
 PHPTAL Wiki ➭ You are here: Wiki Homepage ➭ Integrating with Frameworks

Recent Changes

The following pages were changed recently.

  • 2009/10/08 10:44 Show differences to current revisions Old revisions Upgrading from older releases – Kornel
  • 2009/10/04 01:06 Show differences to current revisions Old revisions Integrating with Frameworks – Kornel
  • 2009/09/23 11:26 Show differences to current revisions Old revisions Prefilters – Kornel
  • 2009/09/23 11:22 Show differences to current revisions Old revisions Wiki Homepage – Kornel
  • 2009/09/23 11:20 Show differences to current revisions Old revisions Custom cache – created Kornel
  • 2009/09/19 14:24 Show differences to current revisions Old revisions Quick Start – Kornel
  • 2009/09/19 03:04 Show differences to current revisions Old revisions Lint tool – Kornel
frameworks.txt · Last modified: 2009/10/04 01:06 by Kornel
Page History | What links here
All Recent changes (as feed) | Contact | © 2005-2009 Motion-Twin, Aardvark Media Ltd.
Except where otherwise noted, content on this wiki is licensed under the following license:GNU Free Documentation License 1.2


PHPTAL Wiki :: Integrating with Frameworks

  • News
  • Introduction
  • Download
  • Manuals
  • FAQ
  • Mailinglist
  • Wiki
 PHPTAL Wiki ➭ You are here: Wiki Homepage ➭ Integrating with Frameworks

Backlinks

This is a list of pages that seem to link back to the current page.

  • Wiki Homepage
frameworks.txt · Last modified: 2009/10/04 01:06 by Kornel
Page History | What links here
All Recent changes (as feed) | Contact | © 2005-2009 Motion-Twin, Aardvark Media Ltd.
Except where otherwise noted, content on this wiki is licensed under the following license:GNU Free Documentation License 1.2


PHPTAL Wiki :: Integrating with Frameworks

  • News
  • Introduction
  • Download
  • Manuals
  • FAQ
  • Mailinglist
  • Wiki
 PHPTAL Wiki ➭ You are here: Wiki Homepage ➭ Integrating with Frameworks

Index

This is an index over all available pages ordered by namespaces.

  • playground
  • wiki
  • Custom cache
  • Prefilters
  • Integrating with Frameworks
  • Lint tool
  • Quick Start
  • Wiki Homepage
  • Upgrading from older releases
  • Zope Page Templates
frameworks.txt · Last modified: 2009/10/04 01:06 by Kornel
Page History | What links here
All Recent changes (as feed) | Contact | © 2005-2009 Motion-Twin, Aardvark Media Ltd.
Except where otherwise noted, content on this wiki is licensed under the following license:GNU Free Documentation License 1.2


PHPTAL Wiki :: Lint tool

  • News
  • Introduction
  • Download
  • Manuals
  • FAQ
  • Mailinglist
  • Wiki
 PHPTAL Wiki ➭ You are here: Wiki Homepage ➭ Lint tool
Table of Contents
  • Lint tool
    • Usage
    • Examples

Lint tool

Lint allows you to check syntax of templates (XML well-formedness) without running them. It is useful to run after upgrade of PHPTAL to ensure that everything still works. You can also use it in SVN pre-commit hook to prevent ill-formed templates from being committed to your repository.

Download latest phptal_lint.php

Usage

This is command-line tool.

 phptal_lint.php [-e extensions] [-i php_file_or_directory] file_or_directory_to_check ...
  • -e comma-separated list of file extensions you use for templates
  • -i path to PHP file or directory of PHP files to include (this is needed to check against your custom TALES modifiers)

Examples

phptal_lint.php .

Scan current directory for all templates (templates are recognized by popular file extensions). TALES modifiers (as in ${mycustommodifier:foo/bar}) will be ignored.

phptal_lint.php -e xhtml,zpt,tal,phtml -i myproject/includes/phptalmodifiers.php myproject/templates/

Checks only *.xhtml, *.zpt, *.tal and *.phtml files in myproject/templates/. Will load myproject/includes/phptalmodifiers.php file first assuming it defines all TALES modifiers used by the templates.

lint.txt · Last modified: 2009/09/19 03:04 by Kornel
Page History | What links here
All Recent changes (as feed) | Contact | © 2005-2009 Motion-Twin, Aardvark Media Ltd.
Except where otherwise noted, content on this wiki is licensed under the following license:GNU Free Documentation License 1.2


PHPTAL Wiki :: Lint tool

  • News
  • Introduction
  • Download
  • Manuals
  • FAQ
  • Mailinglist
  • Wiki
 PHPTAL Wiki ➭ You are here: Wiki Homepage ➭ Lint tool

Old Revisions

These are the older revisons of the current document. To revert to an old revision, select it from below, click Edit this page and save it.

  • 2009/09/19 03:04 [image] lint – Kornel (current)
  • 2009/09/19 03:03 Show differences to current revisions lint – Kornel
  • 2009/09/19 03:03 Show differences to current revisions lint – Kornel
  • 2009/09/19 03:00 Show differences to current revisions lint – Kornel
  • 2009/09/18 18:57 Show differences to current revisions lint – created Kornel
lint.txt · Last modified: 2009/09/19 03:04 by Kornel
Page History | What links here
All Recent changes (as feed) | Contact | © 2005-2009 Motion-Twin, Aardvark Media Ltd.
Except where otherwise noted, content on this wiki is licensed under the following license:GNU Free Documentation License 1.2


PHPTAL Wiki :: Lint tool

  • News
  • Introduction
  • Download
  • Manuals
  • FAQ
  • Mailinglist
  • Wiki
 PHPTAL Wiki ➭ You are here: Wiki Homepage ➭ Lint tool

Edit the page and hit Save. See syntax for Wiki syntax. Please edit the page only if you can improve it. If you want to test some things, learn to make your first steps on the playground.

Media Files
Note: By editing this page you agree to license your content under the following license: GNU Free Documentation License 1.2
lint.txt · Last modified: 2009/09/19 03:04 by Kornel
Page History | What links here
All Recent changes (as feed) | Contact | © 2005-2009 Motion-Twin, Aardvark Media Ltd.
Except where otherwise noted, content on this wiki is licensed under the following license:GNU Free Documentation License 1.2


lint

Table of Contents
  • Lint tool
    • Usage
    • Examples

Lint tool

Lint allows you to check syntax of templates (XML well-formedness) without running them. It is useful to run after upgrade of PHPTAL to ensure that everything still works. You can also use it in SVN pre-commit hook to prevent ill-formed templates from being committed to your repository.

Download latest phptal_lint.php

Usage

This is command-line tool.

 phptal_lint.php [-e extensions] [-i php_file_or_directory] file_or_directory_to_check ...
  • -e comma-separated list of file extensions you use for templates
  • -i path to PHP file or directory of PHP files to include (this is needed to check against your custom TALES modifiers)

Examples

phptal_lint.php .

Scan current directory for all templates (templates are recognized by popular file extensions). TALES modifiers (as in ${mycustommodifier:foo/bar}) will be ignored.

phptal_lint.php -e xhtml,zpt,tal,phtml -i myproject/includes/phptalmodifiers.php myproject/templates/

Checks only *.xhtml, *.zpt, *.tal and *.phtml files in myproject/templates/. Will load myproject/includes/phptalmodifiers.php file first assuming it defines all TALES modifiers used by the templates.


PHPTAL Wiki :: Lint tool

  • News
  • Introduction
  • Download
  • Manuals
  • FAQ
  • Mailinglist
  • Wiki
 PHPTAL Wiki ➭ You are here: Wiki Homepage ➭ Lint tool

Recent Changes

The following pages were changed recently.

  • 2009/10/08 10:44 Show differences to current revisions Old revisions Upgrading from older releases – Kornel
  • 2009/10/04 01:06 Show differences to current revisions Old revisions Integrating with Frameworks – Kornel
  • 2009/09/23 11:26 Show differences to current revisions Old revisions Prefilters – Kornel
  • 2009/09/23 11:22 Show differences to current revisions Old revisions Wiki Homepage – Kornel
  • 2009/09/23 11:20 Show differences to current revisions Old revisions Custom cache – created Kornel
  • 2009/09/19 14:24 Show differences to current revisions Old revisions Quick Start – Kornel
  • 2009/09/19 03:04 Show differences to current revisions Old revisions Lint tool – Kornel
lint.txt · Last modified: 2009/09/19 03:04 by Kornel
Page History | What links here
All Recent changes (as feed) | Contact | © 2005-2009 Motion-Twin, Aardvark Media Ltd.
Except where otherwise noted, content on this wiki is licensed under the following license:GNU Free Documentation License 1.2


PHPTAL Wiki :: Lint tool

  • News
  • Introduction
  • Download
  • Manuals
  • FAQ
  • Mailinglist
  • Wiki
 PHPTAL Wiki ➭ You are here: Wiki Homepage ➭ Lint tool

Backlinks

This is a list of pages that seem to link back to the current page.

  • Wiki Homepage
lint.txt · Last modified: 2009/09/19 03:04 by Kornel
Page History | What links here
All Recent changes (as feed) | Contact | © 2005-2009 Motion-Twin, Aardvark Media Ltd.
Except where otherwise noted, content on this wiki is licensed under the following license:GNU Free Documentation License 1.2


PHPTAL Wiki :: Lint tool

  • News
  • Introduction
  • Download
  • Manuals
  • FAQ
  • Mailinglist
  • Wiki
 PHPTAL Wiki ➭ You are here: Wiki Homepage ➭ Lint tool

Index

This is an index over all available pages ordered by namespaces.

  • playground
  • wiki
  • Custom cache
  • Prefilters
  • Integrating with Frameworks
  • Lint tool
  • Quick Start
  • Wiki Homepage
  • Upgrading from older releases
  • Zope Page Templates
lint.txt · Last modified: 2009/09/19 03:04 by Kornel
Page History | What links here
All Recent changes (as feed) | Contact | © 2005-2009 Motion-Twin, Aardvark Media Ltd.
Except where otherwise noted, content on this wiki is licensed under the following license:GNU Free Documentation License 1.2


PHPTAL Wiki :: Quick Start

  • News
  • Introduction
  • Download
  • Manuals
  • FAQ
  • Mailinglist
  • Wiki
 PHPTAL Wiki ➭ You are here: Wiki Homepage ➭ Quick Start
Table of Contents
  • Quick Start
    • Basics
    • Gathering of data
    • Layout template

Quick Start

Basics

  1. Download latest version
  2. Unpack it in your project or includes directory
  3. Create PHP and template files

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>

Gathering of data

Avoid passing PHPTAL object around your entire program. MVC programs should be independent of their 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();

foreach($result_array as $k => $v) $phptal->set($k,$v);

Layout template

<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.

quickstart.txt · Last modified: 2009/09/19 14:24 by Kornel
Page History | What links here
All Recent changes (as feed) | Contact | © 2005-2009 Motion-Twin, Aardvark Media Ltd.
Except where otherwise noted, content on this wiki is licensed under the following license:GNU Free Documentation License 1.2


PHPTAL Wiki :: Quick Start

  • News
  • Introduction
  • Download
  • Manuals
  • FAQ
  • Mailinglist
  • Wiki
 PHPTAL Wiki ➭ You are here: Wiki Homepage ➭ Quick Start

Old Revisions

These are the older revisons of the current document. To revert to an old revision, select it from below, click Edit this page and save it.

  • 2009/09/19 14:24 [image] quickstart – Kornel (current)
  • 2009/09/19 14:21 Show differences to current revisions quickstart – Kornel
  • 2009/09/19 14:08 Show differences to current revisions quickstart – Kornel
  • 2009/09/19 14:07 Show differences to current revisions quickstart – Kornel
  • 2009/09/19 13:52 Show differences to current revisions quickstart – Kornel
  • 2009/09/19 13:45 Show differences to current revisions quickstart – created Kornel
quickstart.txt · Last modified: 2009/09/19 14:24 by Kornel
Page History | What links here
All Recent changes (as feed) | Contact | © 2005-2009 Motion-Twin, Aardvark Media Ltd.
Except where otherwise noted, content on this wiki is licensed under the following license:GNU Free Documentation License 1.2


PHPTAL Wiki :: Quick Start

  • News
  • Introduction
  • Download
  • Manuals
  • FAQ
  • Mailinglist
  • Wiki
 PHPTAL Wiki ➭ You are here: Wiki Homepage ➭ Quick Start

Edit the page and hit Save. See syntax for Wiki syntax. Please edit the page only if you can improve it. If you want to test some things, learn to make your first steps on the playground.

Media Files
Note: By editing this page you agree to license your content under the following license: GNU Free Documentation License 1.2
quickstart.txt · Last modified: 2009/09/19 14:24 by Kornel
Page History | What links here
All Recent changes (as feed) | Contact | © 2005-2009 Motion-Twin, Aardvark Media Ltd.
Except where otherwise noted, content on this wiki is licensed under the following license:GNU Free Documentation License 1.2


quickstart

Table of Contents
  • Quick Start
    • Basics
    • Gathering of data
    • Layout template

Quick Start

Basics

  1. Download latest version
  2. Unpack it in your project or includes directory
  3. Create PHP and template files

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>

Gathering of data

Avoid passing PHPTAL object around your entire program. MVC programs should be independent of their 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();

foreach($result_array as $k => $v) $phptal->set($k,$v);

Layout template

<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.


PHPTAL Wiki :: Quick Start

  • News
  • Introduction
  • Download
  • Manuals
  • FAQ
  • Mailinglist
  • Wiki
 PHPTAL Wiki ➭ You are here: Wiki Homepage ➭ Quick Start

Recent Changes

The following pages were changed recently.

  • 2009/10/08 10:44 Show differences to current revisions Old revisions Upgrading from older releases – Kornel
  • 2009/10/04 01:06 Show differences to current revisions Old revisions Integrating with Frameworks – Kornel
  • 2009/09/23 11:26 Show differences to current revisions Old revisions Prefilters – Kornel
  • 2009/09/23 11:22 Show differences to current revisions Old revisions Wiki Homepage – Kornel
  • 2009/09/23 11:20 Show differences to current revisions Old revisions Custom cache – created Kornel
  • 2009/09/19 14:24 Show differences to current revisions Old revisions Quick Start – Kornel
  • 2009/09/19 03:04 Show differences to current revisions Old revisions Lint tool – Kornel
quickstart.txt · Last modified: 2009/09/19 14:24 by Kornel
Page History | What links here
All Recent changes (as feed) | Contact | © 2005-2009 Motion-Twin, Aardvark Media Ltd.
Except where otherwise noted, content on this wiki is licensed under the following license:GNU Free Documentation License 1.2


PHPTAL Wiki :: Quick Start

  • News
  • Introduction
  • Download
  • Manuals
  • FAQ
  • Mailinglist
  • Wiki
 PHPTAL Wiki ➭ You are here: Wiki Homepage ➭ Quick Start

Backlinks

This is a list of pages that seem to link back to the current page.

  • Wiki Homepage
quickstart.txt · Last modified: 2009/09/19 14:24 by Kornel
Page History | What links here
All Recent changes (as feed) | Contact | © 2005-2009 Motion-Twin, Aardvark Media Ltd.
Except where otherwise noted, content on this wiki is licensed under the following license:GNU Free Documentation License 1.2


PHPTAL Wiki :: Quick Start

  • News
  • Introduction
  • Download
  • Manuals
  • FAQ
  • Mailinglist
  • Wiki
 PHPTAL Wiki ➭ You are here: Wiki Homepage ➭ Quick Start

Index

This is an index over all available pages ordered by namespaces.

  • playground
  • wiki
  • Custom cache
  • Prefilters
  • Integrating with Frameworks
  • Lint tool
  • Quick Start
  • Wiki Homepage
  • Upgrading from older releases
  • Zope Page Templates
quickstart.txt · Last modified: 2009/09/19 14:24 by Kornel
Page History | What links here
All Recent changes (as feed) | Contact | © 2005-2009 Motion-Twin, Aardvark Media Ltd.
Except where otherwise noted, content on this wiki is licensed under the following license:GNU Free Documentation License 1.2


====== Quick Start ====== ===== Basics ===== - [[http://phptal.org/download.html|Download]] latest version - Unpack it in your project or includes directory - Create PHP and template files ''index.php'':
who_to_greet = "World";

// execute() returns result of template
echo $phptal->execute();
 ''hello.xhtml'':

Hello !

 ===== Gathering of data ===== Avoid passing PHPTAL object around your entire program. MVC programs should be independent of their 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. $v) $phptal->set($k,$v); ===== Layout template ====== ''[[http://phptal.org/manual/en/split/phptal-blocks.html|]]'' 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 ''
'' or ''''. [[http://phptal.org/manual/en/#metal|METAL]] macros can be used to execute code from other templates. Conceptually macros are very similar to PHP functions: | function name() {…} |
…
 | | name(); |
| | function name($argument_name) {…} |
| | name("argument data"); |
argument data
 | ''main.xhtml'': <tal:block metal:define-slot="other-stuff-in-head"/> </head> <body> <div id="main"><tal:block metal:define-slot="maincontent"/></div> </body> </html> </code> ''subpage.xhtml'': <code xml> <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> </code> Note that the code didn't use ''metal:*-slot'' to set title of the page. Macros "see" variables [[http://phptal.org/manual/en/split/tal-define.html|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.


PHPTAL Wiki :: Wiki Homepage

  • News
  • Introduction
  • Download
  • Manuals
  • FAQ
  • Mailinglist
  • Wiki
 PHPTAL Wiki ➭ Start

Old Revisions

These are the older revisons of the current document. To revert to an old revision, select it from below, click Edit this page and save it.

  • 2009/09/23 11:22 [image] start – Kornel (current)
  • 2009/09/23 11:12 Show differences to current revisions start – Kornel
  • 2009/09/19 23:16 Show differences to current revisions start – 82.132.139.149
  • 2009/09/19 23:15 Show differences to current revisions start – 82.132.139.149
  • 2009/09/19 23:14 Show differences to current revisions start – 82.132.139.149
  • 2009/09/18 18:58 Show differences to current revisions start – Kornel
  • 2009/09/18 18:32 Show differences to current revisions start – Kornel
  • 2009/09/17 23:21 Show differences to current revisions start – 87.112.9.128
  • 2009/09/17 01:50 Show differences to current revisions start – Kornel
  • 2009/09/16 21:05 Show differences to current revisions start – 87.112.9.128
  • 2009/09/16 16:05 Show differences to current revisions start – 195.235.92.25
  • 2009/09/16 16:04 Show differences to current revisions start – 195.235.92.25
  • 2009/09/16 12:44 Show differences to current revisions start – 82.70.200.181
  • 2009/09/16 12:39 Show differences to current revisions start – created 82.70.200.181
start.txt · Last modified: 2009/09/23 11:22 by Kornel
Page History | What links here
All Recent changes (as feed) | Contact | © 2005-2009 Motion-Twin, Aardvark Media Ltd.
Except where otherwise noted, content on this wiki is licensed under the following license:GNU Free Documentation License 1.2


PHPTAL Wiki :: Wiki Homepage

  • News
  • Introduction
  • Download
  • Manuals
  • FAQ
  • Mailinglist
  • Wiki
 PHPTAL Wiki ➭ Start

Edit the page and hit Save. See syntax for Wiki syntax. Please edit the page only if you can improve it. If you want to test some things, learn to make your first steps on the playground.

Media Files
Note: By editing this page you agree to license your content under the following license: GNU Free Documentation License 1.2
start.txt · Last modified: 2009/09/23 11:22 by Kornel
Page History | What links here
All Recent changes (as feed) | Contact | © 2005-2009 Motion-Twin, Aardvark Media Ltd.
Except where otherwise noted, content on this wiki is licensed under the following license:GNU Free Documentation License 1.2


start

Wiki Homepage

This is incubator for PHPTAL documentation and ideas. Don't hesitate to share your code samples and tips, plugins, wrappers for 3rd party libraries/frameworks, etc.

You can edit all pages! Just press Edit this page button top in navigation bar. To create new page, [[link]] to it first.

  • QuickStart tutorial
  • Integration with popular PHP frameworks
  • Zope Page Templates - links and specifications from the original TAL implementation
  • Upgrading
  • Lint tool for checking template syntax

Planned features

  • Custom cache plugins
  • Advanced prefilters


PHPTAL Wiki :: Wiki Homepage

  • News
  • Introduction
  • Download
  • Manuals
  • FAQ
  • Mailinglist
  • Wiki
 PHPTAL Wiki ➭ Start

Recent Changes

The following pages were changed recently.

  • 2009/10/08 10:44 Show differences to current revisions Old revisions Upgrading from older releases – Kornel
  • 2009/10/04 01:06 Show differences to current revisions Old revisions Integrating with Frameworks – Kornel
  • 2009/09/23 11:26 Show differences to current revisions Old revisions Prefilters – Kornel
  • 2009/09/23 11:22 Show differences to current revisions Old revisions Wiki Homepage – Kornel
  • 2009/09/23 11:20 Show differences to current revisions Old revisions Custom cache – created Kornel
  • 2009/09/19 14:24 Show differences to current revisions Old revisions Quick Start – Kornel
  • 2009/09/19 03:04 Show differences to current revisions Old revisions Lint tool – Kornel
start.txt · Last modified: 2009/09/23 11:22 by Kornel
Page History | What links here
All Recent changes (as feed) | Contact | © 2005-2009 Motion-Twin, Aardvark Media Ltd.
Except where otherwise noted, content on this wiki is licensed under the following license:GNU Free Documentation License 1.2


PHPTAL Wiki :: Wiki Homepage

  • News
  • Introduction
  • Download
  • Manuals
  • FAQ
  • Mailinglist
  • Wiki
 PHPTAL Wiki ➭ Start

Backlinks

This is a list of pages that seem to link back to the current page.

Nothing was found.

start.txt · Last modified: 2009/09/23 11:22 by Kornel
Page History | What links here
All Recent changes (as feed) | Contact | © 2005-2009 Motion-Twin, Aardvark Media Ltd.
Except where otherwise noted, content on this wiki is licensed under the following license:GNU Free Documentation License 1.2


PHPTAL Wiki :: Wiki Homepage

  • News
  • Introduction
  • Download
  • Manuals
  • FAQ
  • Mailinglist
  • Wiki
 PHPTAL Wiki ➭ Start

Index

This is an index over all available pages ordered by namespaces.

  • playground
  • wiki
  • Custom cache
  • Prefilters
  • Integrating with Frameworks
  • Lint tool
  • Quick Start
  • Wiki Homepage
  • Upgrading from older releases
  • Zope Page Templates
start.txt · Last modified: 2009/09/23 11:22 by Kornel
Page History | What links here
All Recent changes (as feed) | Contact | © 2005-2009 Motion-Twin, Aardvark Media Ltd.
Except where otherwise noted, content on this wiki is licensed under the following license:GNU Free Documentation License 1.2


PHPTAL Wiki :: Upgrading from older releases

  • News
  • Introduction
  • Download
  • Manuals
  • FAQ
  • Mailinglist
  • Wiki
 PHPTAL Wiki ➭ You are here: Wiki Homepage ➭ Upgrading from older releases
Table of Contents
  • Upgrading from older releases
    • 1.1.14 → 1.2.0
      • Entities and encodings
      • Constants
      • XML
      • Other issues
    • 1.1.x → 1.1.14

Upgrading from older releases

These are only changes that could affect existing templates. You'll find all those instructions and additional information about changes/features in release annoucements.

1.1.14 → 1.2.0

Entities and encodings

The biggest difference is in handling of entities. Entities are now unescaped before passing to expressions, i.e. ${php:strlen('&quot;')} “sees” just the quote character and returns 1. In previous versions entities were passed as-is to the expressions (and that example would return 6).

Newly added unescaping of entities can expose encoding bugs. Make sure your pages declare document encoding: For XHTML it's best to send Content-Type:application/xhtml+xml;charset=UTF-8 or Content-Type:text/html;charset=UTF-8 HTTP headers.

  • Don't use text/xml MIME type, use application/xml instead.

In HTML add appropriate <meta> tag or send Content-Type:text/html;charset=UTF-8 HTTP header.

  • If you're not using UTF-8 encoding, you must set encoding you use via $phptal->setEncoding('ISO-8859-…') (or just switch to UTF-8 already! :)
  • Only some 8-bit-based encodings are supported. If your encoding is not supported, you may get away with setting ISO-8859-1 instead.

Constants

  • All constants except PHPTAL_VERSION have been removed. Remove any PHPTAL-specific define()s and use class methods (available in earlier versions too) for configuration (e.g. $phptal->setPhpCodeDestination('/tmp/phptal/') for custom temp directory.)
  • PHPTAL_DIR is gone. PHPTAL now temporarily modifies include_path (this may change in the future).
  • Don't include any PHPTAL's files before including PHPTAL.php.

XML

  • XML namespace of phptal:* attributes has changed from http://xml.zope.org/namespaces/phptal to http://phptal.org/ns/phptal.
  • Comments are required to be well-formed (-- is not allowed in comments.) Comments starting with <!--! are stripped from output.
  • Duplicate attributes are not allowed and they must be separated with space. <b title=""title=""> is doubly wrong.

Other issues

  • use | nothing instead of | false to avoid getting zeros (false is now printed as 0).
  • tal:repeat doesn't “leak” variables to outer scope
  • Internal DOM classes have been refactored. Your custom TAL attributes could break – if they did, please complain on the mailinglist!

1.1.x → 1.1.14

In 1.1.13 translation key like <p i18n:translate="'żółw'" /> was interpreted as <p i18n:translate="'<C197><C188><C195><C179><C197><C130>w'"> and you had to use msgid "<C197><C188><C195><C179><C197><C130>w" in your .po files.

PHPTAL 1.1.14 stops doing this and keys are now left unchanged. The example above would simply expect msgid "żółw" in the .po file.

If you don't want to change your .po files and want to keep old behaviour, then call setCanonicalize(true) of PHPTAL_GetTextTranslator, e.g.:

 $translator = new PHPTAL_GetTextTranslator();
 $translator->setLanguage(…);
 $translator->setCanonicalize(true); // add this line
 $phptal->setTranslator($translator);

To upgrade templates, change <Cxxx> back to bytes. This code snippet will do it: preg_replace('/<C(\d+)>/e','chr("\1")',$po_file_content)

upgrading.txt · Last modified: 2009/10/08 10:44 by Kornel
Page History | What links here
All Recent changes (as feed) | Contact | © 2005-2009 Motion-Twin, Aardvark Media Ltd.
Except where otherwise noted, content on this wiki is licensed under the following license:GNU Free Documentation License 1.2


PHPTAL Wiki :: Zope Page Templates

  • News
  • Introduction
  • Download
  • Manuals
  • FAQ
  • Mailinglist
  • Wiki
 PHPTAL Wiki ➭ You are here: Wiki Homepage ➭ Zope Page Templates
Table of Contents
  • Zope Page Templates
      • Specifications
      • Manuals

Zope Page Templates

PHPTAL started as a PHP port of, python based, Zope Page Templates. Some functionality is different and some features available in PHPTAL are not in ZPT and the other way around.
So take the information in the following links with a pinch of salt.

Specifications

  • TAL 1.4 specification
  • Tales 1.3 specification
  • METAL 1.1 specification

Manuals

  • Using ZPT
  • Advanced ZPT
  • ZPT Reference
zopepagetemplates.txt · Last modified: 2009/09/16 16:16 by 195.235.92.25
Page History | What links here
All Recent changes (as feed) | Contact | © 2005-2009 Motion-Twin, Aardvark Media Ltd.
Except where otherwise noted, content on this wiki is licensed under the following license:GNU Free Documentation License 1.2


PHPTAL Wiki :: Zope Page Templates

  • News
  • Introduction
  • Download
  • Manuals
  • FAQ
  • Mailinglist
  • Wiki
 PHPTAL Wiki ➭ You are here: Wiki Homepage ➭ Zope Page Templates

Old Revisions

These are the older revisons of the current document. To revert to an old revision, select it from below, click Edit this page and save it.

  • 2009/09/16 16:16 [image] zopepagetemplates – created 195.235.92.25 (current)
zopepagetemplates.txt · Last modified: 2009/09/16 16:16 by 195.235.92.25
Page History | What links here
All Recent changes (as feed) | Contact | © 2005-2009 Motion-Twin, Aardvark Media Ltd.
Except where otherwise noted, content on this wiki is licensed under the following license:GNU Free Documentation License 1.2


PHPTAL Wiki :: Zope Page Templates

  • News
  • Introduction
  • Download
  • Manuals
  • FAQ
  • Mailinglist
  • Wiki
 PHPTAL Wiki ➭ You are here: Wiki Homepage ➭ Zope Page Templates

Edit the page and hit Save. See syntax for Wiki syntax. Please edit the page only if you can improve it. If you want to test some things, learn to make your first steps on the playground.

Media Files
Note: By editing this page you agree to license your content under the following license: GNU Free Documentation License 1.2
zopepagetemplates.txt · Last modified: 2009/09/16 16:16 by 195.235.92.25
Page History | What links here
All Recent changes (as feed) | Contact | © 2005-2009 Motion-Twin, Aardvark Media Ltd.
Except where otherwise noted, content on this wiki is licensed under the following license:GNU Free Documentation License 1.2


zopepagetemplates

Table of Contents
  • Zope Page Templates
      • Specifications
      • Manuals

Zope Page Templates

PHPTAL started as a PHP port of, python based, Zope Page Templates. Some functionality is different and some features available in PHPTAL are not in ZPT and the other way around.
So take the information in the following links with a pinch of salt.

Specifications

  • TAL 1.4 specification
  • Tales 1.3 specification
  • METAL 1.1 specification

Manuals

  • Using ZPT
  • Advanced ZPT
  • ZPT Reference


PHPTAL Wiki :: Zope Page Templates

  • News
  • Introduction
  • Download
  • Manuals
  • FAQ
  • Mailinglist
  • Wiki
 PHPTAL Wiki ➭ You are here: Wiki Homepage ➭ Zope Page Templates

Recent Changes

The following pages were changed recently.

  • 2009/10/08 10:44 Show differences to current revisions Old revisions Upgrading from older releases – Kornel
  • 2009/10/04 01:06 Show differences to current revisions Old revisions Integrating with Frameworks – Kornel
  • 2009/09/23 11:26 Show differences to current revisions Old revisions Prefilters – Kornel
  • 2009/09/23 11:22 Show differences to current revisions Old revisions Wiki Homepage – Kornel
  • 2009/09/23 11:20 Show differences to current revisions Old revisions Custom cache – created Kornel
  • 2009/09/19 14:24 Show differences to current revisions Old revisions Quick Start – Kornel
  • 2009/09/19 03:04 Show differences to current revisions Old revisions Lint tool – Kornel
zopepagetemplates.txt · Last modified: 2009/09/16 16:16 by 195.235.92.25
Page History | What links here
All Recent changes (as feed) | Contact | © 2005-2009 Motion-Twin, Aardvark Media Ltd.
Except where otherwise noted, content on this wiki is licensed under the following license:GNU Free Documentation License 1.2


PHPTAL Wiki :: Zope Page Templates

  • News
  • Introduction
  • Download
  • Manuals
  • FAQ
  • Mailinglist
  • Wiki
 PHPTAL Wiki ➭ You are here: Wiki Homepage ➭ Zope Page Templates

Backlinks

This is a list of pages that seem to link back to the current page.

  • Wiki Homepage
zopepagetemplates.txt · Last modified: 2009/09/16 16:16 by 195.235.92.25
Page History | What links here
All Recent changes (as feed) | Contact | © 2005-2009 Motion-Twin, Aardvark Media Ltd.
Except where otherwise noted, content on this wiki is licensed under the following license:GNU Free Documentation License 1.2


PHPTAL Wiki :: Zope Page Templates

  • News
  • Introduction
  • Download
  • Manuals
  • FAQ
  • Mailinglist
  • Wiki
 PHPTAL Wiki ➭ You are here: Wiki Homepage ➭ Zope Page Templates

Index

This is an index over all available pages ordered by namespaces.

  • playground
  • wiki
  • Custom cache
  • Prefilters
  • Integrating with Frameworks
  • Lint tool
  • Quick Start
  • Wiki Homepage
  • Upgrading from older releases
  • Zope Page Templates
zopepagetemplates.txt · Last modified: 2009/09/16 16:16 by 195.235.92.25
Page History | What links here
All Recent changes (as feed) | Contact | © 2005-2009 Motion-Twin, Aardvark Media Ltd.
Except where otherwise noted, content on this wiki is licensed under the following license:GNU Free Documentation License 1.2