Questions are welcome on the PHPTAL mailing list!
&
,<
,"
)?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 <
, 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.
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()),
)),
)),
);
?>
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.
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 :)
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.
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"
Use addPreFilter()
instead of setPreFilter()
. For post-filters create one wrapper "filter":
class MyBunchOfFilters implements PHPTAL_Filter
{
function filter($code)
{
foreach($this->myfilters as $f) $code = $f->filter($code);
return $code;
}
}
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>