PHPTAL

PHP Template Attribute Language

PHPTALのドキュメントを日本語訳しました。
現時点では勝手翻訳なので、この翻訳に関するご意見はtetsuya@wardish.jpまでお願いします。


目次
イントロダクション
なぜPHPTALを使うのか
インストール
最初の例
Template Attribute Language
1. 属性の優先度
2. TAL namespace
2.1. tal:define
2.2. tal:condition
2.3. tal:repeat
2.4. tal:omit-tag
2.5. tal:replace
2.6. tal:content
2.7. tal:attributes
2.8. tal:on-error
3. METAL namespace
3.1. metal:define-macro
3.2. metal:use-macro
3.3. metal:define-slot
3.4. metal:fill-slot
4. I18N namespace
4.1. i18n:translate
4.2. i18n:attributes
4.3. i18n:name
4.4. XHTML in translations
5. PHPTAL namespace
5.1. phptal:debug
5.2. phptal:cache
5.3. phptal:tales
6. tal:block
7. PHPTALES
7.1. path:
7.2. 条件式
7.3. string:
7.4. php:
7.5. not:
7.6. exists:
7.7. default
7.8. structure
7.9. 式の連結
PHP による開発
1. 定数
2. 設定メソッド
3. PHPTAL クラス
4. PHPTAL_Filter インターフェース
5. PHPTAL_Trigger インターフェース
6. PHPTAL_TranslationService インターフェース
6.1. setLanguage(…) メソッド
6.2. useDomain($domain) メソッド
6.3. setVar($key,$value) メソッド
6.4. translate($key) メソッド
6.5. setEncoding($encoding) メソッド
7. gettextの使い方
7.1. Creating the translation directory structure
7.2. Portable Object files
7.3. Translation Domain
7.4. PHP 中での PHPTAL の使い方
7.5. 変数による補間
8. Creating custom expression modifiers
システム管理者のために
Useful links
謝辞

イントロダクション


 PHPTALは Zope Page Template (ZPT)のPHPによるエレガントな実装です。 PHPTALはTAL、METAL、I18N namespaces をサポートしています。
PHPTALESはTALESをシミュレートしており、pythonで書かれたTALテンプレートを容易にPHPへ(逆もまた同様に)移植できます。 TALに対応するために、PHPTALはデータに対してXPath的にアクセスします。
PHPTALはLaurent Bedubourg
<>によって開発され、by Kornel Lesiński.によってメンテナンスされており、LGPLライセンスの元で自由に配布することができます。

なぜPHPTALなのか


 XML/HTMLテンプレートはウェブサービスにおけるロジックとプレゼンテーション(デザイン)を分離するために存在しています。 この分離によって、以下のようなメリットを得ることができます。

ほとんどのテンプレートシステムがセクション検知のために<? ?><% %> もしくは <xxx:yyy></xxx:yyy> のようなタグを使います。 これらはテンプレートシステムの開発を容易にしますが、テンプレートのデザイナーにとっては助けになりません。
TALは、そのほとんどのロジックをXMLの属性として隠蔽するので、XHTMLの構造と文法をくずすことはありません。
なので、TALのテンプレートはWebブラウザ(WYSIWYGエディタ等のライブプレビューでも)でプレビューできますし、プログラマーのエディタによるハイライト表示も可能です。
もしあなたがいつもシンプルなテンプレートシステムを使っているなら、以下のようなコードとなるでしょう。

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

これをPHPTALで書くとこうなります。

<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>

上記のコードはWebブラウザー上で正しくサンプルテキストを表示できますから、もし変数’myarray’がまだ存在していなくてもあなたのクライアントに対してプレゼンテーションを行うことができます。
それ以外のPHPTALの大きなアドバンテージとしては、PHPTALはZopeコミュニティにより3年以上もの間、経験、ドキュメント、例、およびヘルプが蓄積されていることが挙げられます。 PHPTALは、このコミュニティによる豊富な提供物を享受することができます。

PHPTALは開発者やパフォーマンスを要求するシステムのためにカスタマイズできるように設計されています。 が、快適さとシンプルな振る舞いで初心者でも簡単に使えるままにしておいてください。(私はそう努めています:)

インストール


 PHPTALはPEARパッケージ(http://pear.php.netを参照)によってリリースされています。
PHPTALのライブラリーはPHPTALのウェブサイト(http://phptal.org)からダウンロードすることができます。
pearのユーティリティを使う場合
pear install http://phptal.org/latest.tar.gz

一度インストールしてしまえば、PEARを使ってアップデートすることができます。

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

もしあなたがPEARを使いたくない場合、もしくはあなたのシステムにインストールされていない場合は、アーカイブをダウンロードした後に解凍することでもインストールできます。

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

これによりPHPTAL.phpPHPTALフォルダが /path/to/your/lib/folder にインストールされます。

最初の例


 PHPTALの使い勝手を体験するためには、多くの言葉よりも簡単な例のほうが良いでしょう。
以下のような妥当なxml/htmlドキュメント(ルートエレメントを持った)を用意し、’my_template_file.html’と名前を付けてください。
<?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>

php側では、PHPTALライブラリをインクルードし、テンプレートシステムのいくつかの項目を設定してください。

<?php
require_once 'PHPTAL.php';// create a new template object
$template = new PHPTAL('my_template_file.html');
// 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;
}
?>

この状態でPHPスクリプトを実行すれば、以下のような結果が得られます。

<?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は出力の際にファイル中の改行やインデントをあまり意識しません。
もしあなたが出力されるHTMLがきれいである(改行とインデントが施されている)ことを望むのであれば、HTML Tidyによって後処理する必要があるでしょう。

Template Attribute Language


目次
1. Attribute の優先度
2. TAL namespace
2.1. tal:define
2.2. tal:condition
2.3. tal:repeat
2.4. tal:omit-tag
2.5. tal:replace
2.6. tal:content
2.7. tal:attributes
2.8. tal:on-error
3. METAL namespace
3.1. metal:define-macro
3.2. metal:use-macro
3.3. metal:define-slot
3.4. metal:fill-slot
4. I18N namespace
4.1. i18n:translate
4.2. i18n:attributes
4.3. i18n:name
4.4. XHTML in translations
5. PHPTAL namespace
5.1. phptal:debug
5.2. phptal:cache
5.3. phptal:tales
6. tal:block
7. PHPTALES
7.1. path:
7.2. Conditional statements
7.3. string:
7.4. php:
7.5. not:
7.6. exists:
7.7. default
7.8. structure
7.9. Expression chains

 このセクションではTALとその拡張について説明します。 これは主にテンプレートのデザイナーを対象としていますが、PHPの開発者も同様に読んでおいてください。

1. Attribute の優先度

属性の宣言の順序は無関係であることに注意してください。

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

これは、以下と全く同一です。

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

優先度はTALの仕様と同等です。

  1. define
  2. condition
  3. repeat
  4. content or replace
  5. attributes
  6. omit-tag

2. TAL namespace

2.1. tal:define

このattributeは、このテンプレートにおいて後で使うための一つまたは一つ以上の変数を定義します。
これは長いパスへのショートカットの例です。

<span tal:define="global destname path/to/existing/variable" />

テンプレート内で利用する文字列を定義します。

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

複数の変数を同一の内容で定義します。

<span tal:define="global fname string:paul; lname string:dupond" />

他の変数を含んだ変数を定義します。

<span tal:define="global hello string:hello $fname welcome on this page" />

出力バッファを利用したちょっとした小技です。

<span tal:define="global hello">hello ${fname} welcome on this page</span>

tal:defineを他のattributesと一緒に使う場合、他のattributesに先んじて実行されます。
上記の例では、spanタグは表示されません。 なぜなら、出力対象となるコンテントでもattributesでも無いからです。
最後の例でさえ、変数’hello’に代入されるので表示されません。
では、

<span tal:define="hello string:hello ${fname} welcome on this page"
      tal:content="hello"
/>

であれば定義と出力は同時に行われるでしょうか?

いいえ、そうではありません。
なぜなら実行される前にtal:defineはノードの中身を処理しますが、ノードの中身はtal:contentです。
spanの中身は何であっても無視され、その結果、helloは定義されず例外が投げられます。

<span tal:define="hello" tal:content="hello">  hello ${fname} welcome on this page
</span>

上記の例では、’global’キーワードが変数の前に付けられています。
PHPTALでは、変数を定義する際にグローバルかローカルを選択することができます。

グローバルな変数は、テンプレートやマクロ内のすべてのXMLノードから参照することができます。

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

反対に、ローカルな変数は定義されたそのタグの中でのみ有効です。

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

2.2. tal:condition

評価した結果が真の場合のみ、このエンティティとコンテントを出力します。

<span tal:condition="identified"> Welcome member ...  </span>
<span tal:condition="not: identified">
  Please login before accessing this page
</span>

もしPHP側でメソッドが用意されていない場合、特定の状態のためにテンプレート側でPHPによる処理を記述しなければならないでしょう。

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

これではテンプレート内に余計な処理が入ってしまいますので、論理的属性やアクセスしやすいメソッドをテンプレートのために提供するのが良いでしょう。

<span tal:condition="cart/hasMoreThanFiveItems">...</span>
<span tal:condition="fullfillNumerousItems">...</span>

2.3. tal:repeat

このattributeはarrayやassociative arrayやPHP5のIteratableをimplementしたオブジェクト等のような反復可能なオブジェクトを扱います。
このrepeat attributeはそのエレメントとそのコンテントを、指定されたリソースの終わりが来るまで繰り返します。

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

ループの間、repeat/*パスを使うことで、現時点のループの(およびその親のループの)情報を参照することができます。

“item”はtal:repeat式の中で戻り値として定義された変数です。

多くの場合tal:repeatは何かしらのSQLの結果に対して利用します。
以下のコードはplayersRankingがPHPのIteratorを実装したオブジェクトである場合に動作します。

<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>

2.4. tal:omit-tag

このattributeはPHPTALのパーサーに対して、開始タグと終了タグを無視するように指示します。 ただし、内容は評価されます。

<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>

出力は以下の様になります。(訳者註 上記の例の実行結果ではありません)

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

このattributeは任意のエレメントを生成したいときに役に立ちます。 たとえば、特定の条件下でリンクを隠したい場合などです。
もしエレメントも出力したくなければ、tal:blockを使ってください。

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

2.5. tal:replace

このattributeはタグ全体を値で置き換えます。 値が無い場合は何も表示しません。

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

実行結果はこんな感じ

this beautyful string

tal:replace はテンプレート中のサンプルとして記載したいが、最終的な成果物からは取り除きたい場合に利用できます。

<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>

2.6. tal:content

このattributeはタグのコンテントを式の実行結果で置き換えます。

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

実行結果はこんな感じ

<span>my string</span>

2.7. tal:attributes

このattributeはタグ属性の値を置き換えます。(複数指定可)

<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>

somelink‘ が以下であった場合

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

実行結果はこんな感じ

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

セミコロン(;)で属性を区切ることができます。
もし、セミコロン自体を属性に出力したいときは、二つ重ねてください(;;

次はtal:repeatに関わる、若干複雑な例です。

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

この php: モディファイアは後ほど説明しますが、単純に、行が偶数ならtrのclass属性の値を”odd”に、そうでなければclass属性を無しにします。

この”condition ? then : else” は慎重に利用しなければならないPHPの書式ですが、今回はメリットが大きいと判断して利用しています。
同じ結果を得るためのより良い方法は、ロジックの担当者に対してニーズに合ったカスタムモディファイア(PHP による開発 / カスタムモディファイア を参照)を作成してもらうことです。
たとえば以下のように。

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

このモディファイアはrepeat/ranking/oddがtrueの場合に”odd”を返し、falseの場合は何も返さないように作られています。
The modifier would return “odd” if repeat/ranking/odd is true,

2.7.1. Optional attributes

もしあなたが代替手段としてtal:attributesnothing(もしくはPHPにおけるNULL)を使うのであれば、属性は追加されません。(これは空の属性が追加されることを避けるためです。)

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

selectedcheckedのようなXHTML属性は自動的に扱われます。

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

覚えておいていただきたいのは、XHMLはcase-sensitiveである(大文字小文字を意識する)ことです。 ですので、SELECTED属性はXHTMLでは認められません。
selectedと指定してください。

2.8. tal:on-error

このattributeはtal:on-error式の評価において、パスの誤りを検出した場合やPHPのexception(例外)が投げられた場合に、タグを置き換えます。

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

もし’name’や’user’へのアクセスにエラーが発生した場合、エラーメッセージがタグの場所に表示されます。
これはまたこのテンプレート以外にも働きます。

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

3. METAL namespace

METALは’Macro extension for TAL’という意味です。
このnamespaceはPHPTALによってサポートされており、デザイナーがXML/XHTMLのマクロを定義し、呼び出せるようになっています。

3.1. metal:define-macro

このattributeはマクロを定義します。
マクロとは、小さなテンプレートを他の場所でも再利用できるライブラリのようなものと考えてください。

<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>

マクロは呼び出し元のdictionary(コンテキスト)を引き継ぎます。 上記の例では、変数’mdate’はマクロの呼び出しもとテンプレートに依存します。

3.2. metal:use-macro

このattributeはマクロを呼び出し、テンプレート内に展開します。

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

外部のテンプレートで宣言されたマクロも参照できます。

<span metal:use-macro="site_macros.html/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.html/main_menu"/>

マクロは自分自身を呼び出すこともできます。
この方法で配列を再帰的に出力することができます。

        <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>

3.3. metal:define-slot

このattributeはmetal:define-macroタグの中に現れなければなりません。

スロットは呼び出したテンプレートによって置き換えられます。

スロットは逆の読み込みと考えることができますから、丸ごと一ページのマクロがURLに依存してそのページのスロットをカスタマイズする、といったことができます。
たとえば、ログインしたメンバーに応じた最新ニュースや、利用可能メニューを表示することができます。

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

上記の例では、’news_place‘という名前で定義された場所は、呼び出し元のテンプレートで上書きすることが可能です。
引き続き次のセクションを見てください。

3.4. metal:fill-slot

このattributeはmetal:use-macro内でのみ使うことができます。

この宣言はPHPTALに対し、定義されたスロットをmetal:fill-slotattribute内のコンテンツで置き換えるよう指示します。

<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>
  </ul>
</span>

スロットはシンプルなプッシュテクノロジーによって、カスタマイズおよび再利用可能なテンプレートを定義する機会を提供します。

4. I18N namespace

備考: ’i18n’ は’internationalization’の略です。
このnamespaceによって、デザイナーはテンプレートの実行時に翻訳しなければならないテキストゾーンを指定することができます。

4.1. i18n:translate

このattributeはPHPTALの翻訳システムを利用して翻訳しなければならない文を定義します。

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

上記の例では、PHPTALは’welcome_message’という名前のキーを探し、タグの内容を要求された言語で置き換えます。

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

この用法は少し異なっています。
translationキーが指定されていないので、PHPTALはタグの内容である’Welcome here’をキーとして利用します。
翻訳システムがキー’Welcome here’を理解できるのであれば、正常に翻訳されます。

もし翻訳が見つからなければ、キーが翻訳結果として利用されますので、キーの代わりに文章を使用するのが良い選択であるかもしれません。

覚えておいていただきたいのは、このキーは、動的なキー選択のために変数を含むことができるということです。

<div tal:define="welcome random_welcome_message"/>
<div i18n:translate="welcome">...</div>

4.2. i18n:attributes

どの属性が翻訳されるべきか定義します。
i18n:translateにはセミコロンで分割された、属性とキーのリストで指定します。

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

4.3. i18n:name

このattributeは翻訳変数に値を設定します。

翻訳は、しばしば${xxx}を含み、”xxx“という名前の変数によって必要に応じて動的に補間されます。

この変数の値は、タグとその内容に設定されます。
もし値にタグが必要でないなら、tal:contentの代わりにtal:replaceを使ってください。
tal:omit-tagは、値が連続した文字列であれば助けになるかもしれません。

<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 -->

i18nの利用例です。

<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>

この例における翻訳キーは、このようになるでしょう。

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

PHPTALは翻訳註に、${user}${user/name}に、${mails}${user/nbrMails}に置換します。
PHPTALのi18nに関するこれ以上の情報は、このサイトのPHPセクションを参照してください。

4.4. XHTML in translations

通常、翻訳はテキストだけと思われます。
ですので、PHPTALはすべての”<”をエスケープします。
バージョン1.1.14からはi18n:translate内でstructureを使うことでエスケープを無効化できます。
以下は、

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

以下を得ます

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

注意: これは簡単な場合のみ使えるのでしょうか? 翻訳された文字におけるTAL属性は無視します。翻訳におけるIll-formedなXHTMLはwell-formedなページを壊してしまいます。

5. PHPTAL namespace

この属性はTALの仕様によって定義されているわけではありません。
しかしPHPTALで作業する場合には有用です。

5.1. phptal:debug

この属性は、それが定義されたタグの内容に対して、PHPTALのデバッグ指定を切り替えます

Note

テンプレート内で呼ばれたマクロのエラーをデバッグするためには、マクロを定義するテンプレートにもphptal:debugを指定する必要があります。

デバッグモードでは、ファイル名やテンプレートの行番号を格納しますので、不正なパスにより例外が投げられた場合に、より多くの情報を得ることができます。

<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>

5.2. phptal:cache

この属性は、キャッシュ期限が切れるまで、このタグに含まれる要素すべてがディスク上にキャッシュされ、再評価されないようにします。

Note

キャッシュが有用なのは、外部ファイルのマクロや、データベースアクセスを伴うようなPHP式やオブジェクト等の複雑な要素の場合のみです。
それ以外の場合、非キャッシュされたテンプレートも同じくらい速いでしょう。

このattributeの内容の有効期間(どのくらいの間キャッシュされるのか)は、’d‘、’h‘、’m‘、’s‘サフィックスを伴う数値によって書くことができます。

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

上記の例では、<div> の中身は3時間に一度評価されます。

有効期間には”per“オプションをつけ、キャッシュがどのように共有されるか定義することができます。
これにより、このテンプレートを使うすべてのページでキャッシュを共有することができます。
per url“を付加すると、URLごとのキャッシュを持たせることができます。

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

<ol>は各ページ独立に1日間キャッシュされます。

per expression“と追加することで、式の値ごとにキャッシュを保持することができます。(実行結果は文字列でなければなりません)
ただし、同一のエレメント内で、tal:defineによって定義された変数を参照することができません。

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

<ul>は、objectのidごとに25分間キャッシュされます。

5.2.1. Instant refreshing

キャッシュをクリアする代わりに、perパラメータに対してバージョンや最終更新時刻を付加することは良いアイデアです。
これにより、キャッシュされたテンプレートは、バージョンやタイムスタンプが変わるとすぐにリフレッシュされますから、キャッシュのクリアのために特別な事をする必要はなくなります。

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

5.2.2. Limitations:

5.3. phptal:tales

このattributeによってPHPTALESの挙動を帰ることができます。
通常の挙動はZPTの方法で属性式を解釈することですが、時々、ただ単にPHPが使いたい場合においては結局、いたるところでphp:モディファイアを使うことになります。
PHPTALについてのもう一つの問題としては、PHPTALがパスを解釈する方法です。
たとえば、
myobject/mymethod/property/10/othermethod/hashkeyは、解釈するには比較的長い時間がかかります(ですが、パスが長すぎるかどうかについて、あまり気にしすぎないでください。 最適化するのはそのパフォーマンスが実際に問題になってからにしてください)

PHPTALはmyobjectを受け、それがオブジェクトであることを(実行時に)決定したうえで、’mymethod’がそのオブジェクトの(変数ではなく)メソッドであることを決定します。
そしてそのメソッドをコールし、戻り値がプロパティをもったオブジェクトであることを決定し、それは配列であり、10番目の要素を持ち、そしてそれはまたオブジェクトであり、そのオブジェクトのothermethodは(変数ではなく)メソッドであり、それは戻り値を持ち、その戻り値はオブジェクトであり、キー値’hashkey’に関連した値を持つ。 と。

もちろんこれは極端な例ですし、このプロセスは十分速いので、私たちはあまり気にしません。 しかし、このようなとても長いパスが深いtal:repeatの中で呼ばれたら?D’oH!
phptal:talesは以下の様に私たちの助けになります。

<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>

上記の例は以下と同等であることを覚えておいてください。

<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>

‘php:’モディファイアはそれ自身の章で説明します。

6. tal:block

tal:blockは、多くのTAL属性をもつエレメントを表示させたくない場合のための糖衣文(シンタックスシュガー)です。

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

これは以下と同等です。

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

もう一つ。

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

これは以下と同等です。

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

7. PHPTALES

PHPTALESはtalやmetal等のPHPTAL属性の中で使われる式の文法です。
これまでの例で、いくつかのPHPTALESの例(string:、php:、not: …)を見てきたと思います。

この章ではテンプレート中におけるPHPTALESの使い方について説明します。

TAL属性の値は大抵、一つ以上の式を含み(例:tal:define)、それらの式は’;‘によって分割されます。

7.1. path:

これはTALS式において、何のモディファイアも書かれていない場合のデフォルト動作です。

以下の行は同じ結果をもたらします。

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

${path/to/my/variable}の書式を使えば、テンプレート中や式中の文字列でコンテキスト変数を参照することができます。

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

7.2. 条件式

‘<’ も ‘>’ 属性式から排除しなければなりません。
PHPTALは同等の、古き良き文字列による比較演算子を提供しています。 おそらく、このステートメントのほとんどはtal:condition attributeや、php: 式の中で使われるでしょう。

7.3. string:

式のセパレータは’;'であり、また、’$'マークはパスの開始を意味しますので、以下の様にエスケープする必要があります。
Because expressions are separated by a ‘;’ character, and
because ‘$’ marks the start of a path, you must use:

<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 -->

7.4. php:

この式はPHPの式を実行しますが、’->’はドット’.'に置き換える必要があり、変数のプリフィクスである’$'は省かなければなりません。
空白を挟んだドット’.'は連結を表します。

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: 式は慎重に利用すべきであり、その8割では必要ありません。
しかし、そのテンプレート中で動的に、ユーザーがログインしているかどうかに関わりなく、なんらかの特別なメソッドを呼ぶ必要がある場合、もしくは状態に依存した複雑な形式のデータを検索しなければならない場合などでは必要とされるでしょう。

7.5. not:

この式は一つの論理演算子です。 tal:condition内で便利です。

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

7.6. exists:

この式は、事前にパスが定義されていた場合にtrueを返し、そうでない場合にfalseを返します。 つまりPHPのisset()のように働きます。

通常、存在しないパスを利用様とした場合、”Cannot find variable ‘foo‘ in current scope”の様なエラーを投げます。
このようにして、不確実なパスを最初にチェックしておきます。

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

7.7. default

これは式では無く、キーワードです。
エラーが起きた場合や、何かが定義されていない場合、替わりにタグの内容を値として利用することをデザイナーに許可します。

<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.html" title="Unknown page"
   tal:attributes="href item/href | default; title item/title | default"
   tal:content="item/title | default">Unknown page</a>

上記の例では ‘|’ 文字を利用して替わりの定義や表示を許可しています。

7.8. structure

これも式ではなくキーワードです。
PHPTALテンプレート中で変数を表示する際は、出力のvalidityを確保するためにすべての変数をエンコードすることに注意してください。
しかし、ときどき、HTMLやXMLをそのまま出力したい場合があるかもしれません。

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

上記の例では、$document->title$document->content の値は、そのまま出力可能なHTMLであると仮定してください。

7.9. 式の連結

式は ‘|’ で区切って連結することができます。

‘|’ で区切られた式を実行する際、PHPTALはその式の結果が非null、もしくはエラー無しで無ければ式の実行を停止します。
たとえば、string: 式は常にtrueを返しますので、その後にどのような式が続いたとしても、string: の場所で式の実行は停止します。

連結式の中で、php:式を使うこともできます。

<h1 tal:content="page/title | page/alternativeTitle | php:get_default_title()" />

PHP による開発


目次
1. 定数
2. 設定メソッド
3. PHPTALクラス
4. PHPTAL_Filterインターフェース
5. PHPTAL_Triggerインターフェース
6. PHPTAL_TranslationServiceインターフェース
6.1. setLanguage(…)メソッド
6.2. useDomain($domain)メソッド
6.3. setVar($key,$value)メソッド
6.4. translate($key)メソッド
6.5. setEncoding($encoding)メソッド
7. Working with gettext
7.1. Creating the translation directory structure
7.2. Portable Object files
7.3. Translation Domain
7.4. PHP usage in PHPTAL
7.5. Variable interpolation
8. Creating custom expression modifiers

 この章は開発者を対象とし、使い方、およびシンプルで高度なPHPTALのカスタマイズ方法について説明します。

1. 定数

PHPTALライブラリーをインクルードした後、PHPのコンテキスト中にいくつかの変数が定義されます。
それらはすべてPHPTAL.phpによります。

古いバージョンには設定のための定数がありましたが、それらはメソッドで置き換えられました。

2. 設定メソッド

PHPTALは可能な限り、最も良い標準設定を使用しますので、設定を変更する必要はありません。
PHPTALクラスのすべてのメソッドにおいて、set*メソッドはそのクラスのインスタンスを返します。
これによりメソッドチェーンにすることができます。

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

これらは以下と同等です。

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

これ以外にも、フィルタや国際化などのための set*メソッドがあります。 それらはこのマニュアルの別セクションで説明されています。

3. PHPTALクラス

これはあなたにとってメインのクラスです。 最も一般的なメソッドの使い方は、

<?php// include the library
require_once 'PHPTAL.php';
// instantiate a new PHPTAL object using specified template file
$tpl = new PHPTAL('mytemplate.html');
// 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 templaten";
    echo $e;
}
?>

コンテキスト変数を指定した後に、テンプレートのソースを定義することもできます。

<?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.html');
...
?>

また、外部ファイルの替わりに文字列をテンプレートのソースとして利用することもできます。

<?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;
}
?>

PHPTALはテンプレートソース識別子(通常はテンプレートの実パス)を必要とします。
上記の例では、$srcパラメータのmd5を利用します。

<?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();
// because the source is contained in this file and won't be modified unless
// this file is modified, it is 'faster' to specify __FILE__ as the unique
// source identifier, thus no md5 of $src will be done on each call.
$tpl->setSource($src, __FILE__);
$tpl->title = 'this is my title';
try {
    echo $tpl->execute();
}
catch (Exception $e){
    echo $e;
}
?>

4. PHPTAL_Filterインターフェース

このインターフェースは、テンプレートソースに対する(pre-filters)、もしくはPHPTALの実行結果に対する(post-filters)自動的なフィルターを実現します。
pre-filtersはテンプレートのパース前に呼び出され、テンプレートが変更されるまでは呼び出されることはありません。
post-filtersはテンプレートの展開後に実行されます。

<?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.html');
$tpl->setPreFilter(new MyPreFilter());
$tpl->setPostFilter(new MyPostFilter());

echo $tpl->execute();
?>

set*Filterによって一つのpre-filterと一つのpost-filterをセットすることができます。
もし一つ以上のフィルターを連結して使いたい場合、PHPTAL_Filterに実装されているフィルタ連結インターフェースを使って一つのクラス内にラップすることができます。

<?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.html');
$tpl->setPostFilter($myFilter);

echo $tpl->execute();
?>

5. PHPTAL_Triggerインターフェース

phptal:idattributeはPHP5バージョンから、古いPHPTAL_Cacheインターフェースを置き換え、それらをもう少し要約するためにPHPTALに追加されました。

phptal:idに達した時点で、PHPTALはトリガーリストからidに一致するトリガーを探し、そのstart()とend()メソッドをエレメントの開始時、および終了時に実行します。

もし PHPTAL_Trigger::start() メソッドの戻り値が PHPTAL_Trigger::SKIPTAG である場合、PHPTALはこのエレメントとその内容を無視します。(start()それに変わる何かを出力するかもしれません。)
トリガーの実行にエレメントや内容を必要とするのであれば、 PHPTAL_Trigger::PROCEEDを返す必要があります。

PHPTAL_Trigger::end() は、エレメント終了時に呼ばれます。
これによって、start()内でob_start()を、end()内でob_get_contents()とob_end_clean()を使ったキャッシュシステムを作ることができます。

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

いくつかの理由から、divブロックをキャッシュすることに決め、テンプレートにphptal:idを導入します。

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

そして、divコンテントをキャッシュするトリガーを記述します。

<?php
require_once 'PHPTAL.php';
require_once PHPTAL_DIR.'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;
}
?>

注意すべき点は、SKIPTAGPROCEEDのどちらかがstart()の戻り値となっている点です。
SKIPTAGが返される場合、PHPTALはタグを無視しend()を呼びます。 これは大抵の場合、トリガーはそこに何を表示すべきかを受け取ることを意味します。
PROCEEDが返される場合、PHPTALは通常通りタグと内容を実行し、end()を呼びます。
これにより一度タグを実行し、後で呼び出しに利用されるファイルに結果を保存する出力バッファを取り扱うことができます。
このトリガーをインストールするには以下の様にします。

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

$trigger = new CacheTrigger();
$tpl = new PHPTAL('test.html');
// this trigger will only be called for phptal:id="triggerId"
$tpl->addTrigger('somePossiblyUniqueKeyword', $trigger);
$tpl->id = 1;

echo $tpl->execute();
?>

テンプレートに多くのトリガーを追加することもできます。 一般的なキャッシュトリガーは一つ以上のphptal:idやその他を利用するでしょう。

6. PHPTAL_TranslationServiceインターフェース

PHPTALは他のセクションで示されているように、標準でgettextによる翻訳サービスを利用していますが、独自の翻訳サービスを実装することもできます。
PHPTAL_TranslationServiceインターフェースはそのような時に使います。
使い方はPHPTAL_GetTextTranslatorと同様となるでしょう。

$tpl->setTranslator($yourOwnTranslatorInstance);

以下のメソッドを実装する必要があります。

6.1. setLanguage(…) メソッド

このメソッドはテンプレートの出力言語を切り替える際に呼ばれます。 引数は利用可能な言語です。(引数配列を使うために、func_get_args()を使います)
あなたのサービスではよく知られた言語を使うべきでしょう。

<?php
require_once PHPTAL_DIR.'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;
            return;
        }
    }
    ...
    private $_currentLang;
}
?>

6.2. useDomain($domain) メソッド

もし、翻訳ファイルを分割して保存する場合(例えば アプリケーション毎に一つ)、このメソッドによってテンプレートの翻訳ドメインを選択することができます。(i18n:domain

<?php
require_once PHPTAL_DIR.'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();
}
?>

上記の例では、キーに対応する翻訳を返すPHPファイルによる翻訳ソリューションを実現しています。

6.3. setVar($key,$value) メソッド

このメソッドはi18n:name呼び出しに相当しています。 後の呼び出しのためにcontextに挿入します。

<?php
require_once PHPTAL_DIR.'PHPTAL/TranslationService.php';
class MyTranslator implements PHPTAL_TranslationService {
    ...
    public function setVar($key, $value){
        $this->_context[$key] = $value;
    }
    ...
    private $_context = array();
}
?>

6.4. translate($key) メソッド

最後の重要なメソッドは、あなたの翻訳サービスに現在の選択された言語においてキーに定義された翻訳を問い合せます。

<?php
require_once PHPTAL_DIR.'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;
    }
    ...
}
?>

6.5. setEncoding($encoding) メソッド

PHPTALクラスはあなたの翻訳サービスに、テンプレートで何のエンコーディングが使用されているかを知らせるためにこのメソッドを呼びます。
translate()メソッドはそのエンコーディングの文字列を返さなければなりません。
もしあなたはいつも、テンプレートと翻訳ファイルに同じエンコーディング(たとえばUTF-8)を使うのであれば、このメソッドは空っぽにしてしまっても良いでしょう。

7. Working with gettext

gettext はPHPから使える標準的なGNUの国際化/翻訳システムであり、PHPTALでもサポートされています。
gettextの使い方は単純ですが、あなたのシステムで使えるかどうか確かめるために、いくつかのテストを実行してください。

最初に、PHPが--with-gettextでコンパイルされている必要があります。 コンパイル方法はPHPのドキュメントを見てください。
以下のコードでテストすることができます。

//
// test if gettext extension is installed with php
//if (!function_exists("gettext"))
{
    echo "gettext is not installedn";
}
else
{
    echo "gettext is supportedn";
}

7.1. Creating the translation directory structure

PHPのgettext拡張は、翻訳ファイルを含む特殊な構造を必要とします。

/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 ...

言語コードは2文字で表され、その言語自身(en, fr, es, …)を定義します。 さらに二つの文字は国(US, GB, FR, ES, …)を定義します。
ディレクトリパターンは以下です。

<path_to_where_you_want>/<ll_CC>/LC_MESSAGES/

7.2. Portable Object files

POファイルは翻訳を含んだプレインテキストです。 人手で編集することができます。
もっとも小さなPOファイルの例です。 (en_US/LC_MESSAGES/mydomain.po)

msgid ""
msgstr ""
"Content-Type: text/plain; charset=utf-8n"
"Content-Transfer-Encoding: 8bitn"msgid "Simple test"
msgstr "A small sentence in english"

一度編集したらインデックス化しなければなりません。

msgfmt mydomain.po -o mydomain.mo

あなたのシステムにgettextツールがインストールされていなければ、このコマンドは動作しません。

これにより、翻訳に素早くアクセスするためにインデックス化されたMO(machine object)ファイルが作成されます。

そして、あなたは他の言語でこのファイルを翻訳しなければなりません。

最小の例は以下です (fr_FR/LC_MESSAGES/mydomain.po):

msgid ""
msgstr ""

"Content-Type: text/plain; charset=utf-8n"
"Content-Transfer-Encoding: 8bitn"msgid "Simple test"

msgstr "Une petite phrase en francais"

そしてまた、インデックス化しなければなりません。

msgfmt mydomain.po -o mydomain.mo

7.3. Translation Domain

ドメインはあなたの翻訳ファイルパス名に含まれます。 先ほどまでの例では’mydomain’をドメイン名として利用してきました。
アプリケーションで複数のドメインを持つことができ、一つ以上のファイルに翻訳を分割することでgettextのパフォーマンスを上げることができます。

7.4. PHP 中における PHPTALの使い方

<?php
require_once 'PHPTAL.php';
require_once PHPTAL_DIR.'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.html');

    // tell PHPTAL to use our translator
    $tpl->setTranslator($tr);
}
catch (Exception $e){
    echo $e;
}

7.5. 変数による補間

I18N namespaceは、翻訳に変数を補間することができます。

# english
msgid "welcome"
msgstr "Welcome ${name} you have ${n} mails !"# french
msgid "welcome"
msgstr "Bienvenue ${name} vous avez recu ${n} messages !"

テンプレートはこの補間を以下の様に使うことができます。

<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>

i18n:translateは値’welcome’を含むので、このテンプレートデータは無視されて、gettextによるメッセージが替わりに利用されます。

8. Creating custom expression modifiers

PHPTALは基本の式モディファイアを提供しています(not:, exists:,
string:, php:, path:)。

これらのモディファイアはZPTによって定義されている物ですが、PHPTALは文字列や、日付、会計、オブジェクト、などの操作のためにモディファイアを拡張することができます。
モディファイアの目的は、templateのPHPソースに含まれた何らかのPHPコードを返すことです。
モディファイアはパース時に利用されます。 もしモディファイアの挙動を変えたい場合、生成されたPHPファイルを削除し、そのモディファイアが使われているテンプレートを再度パースしなければなりません。

覚えておいて欲しいのは、モディファイアはコードを生成するべきであって、データを出力してはならないということです。

phptal_tales_“で始まるPHP関数をモディファイアとして利用することができます。
モディファイアは二つの引数を持ちます。

以下のTALテンプレート中の例を見てください。

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

src引数は”my/path/value“となり、$nothrowはfalseとなります。 なぜなら、tal:replaceは常に解決可能なパスを要求するからです。

以下の様な式は、

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

二つのモディファイアが使われています。

path: は、他のモディファイアが指定されていない場合の暗黙のモディファイアであることを忘れないでください。

モディファイアは、簡単なPHPコードを生成するために他のモディファイアを使うことができます。

//
// 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).')';
}

システム管理者のために


 PHPTALの機能は、テンプレートロジックによってPHPファイルを生成生成することです。 このことが意味するのは、それらの生成されたファイルを置くためのディ楽取りが必要であり、それらはPHPインタプリタによってパース可能でなければならないと言うことです。
標準状態のPHPTALでは、システムのテンポラリディレクトリ(有効であれば、PHPのsys_get_temp_dir()の場所)か、Unix系システムであれば/tmp、マイクロソフト系であればc:\windows\tempにコンパイルされたテンプレートを置こうとします。
この標準の出力先はsetPhpCodeDestinationに適切なパスを指定することで変更できます。
システムのテンポラリディレクトリ、もしくは指定されたそのパスは、PHPのプロセス(もし mod_phpならapacheの実行ユーザー、そうでないならcgiやfastcgiのユーザー)がファイルをcreateおよびupdateできるように設定されている必要があります。
PHPTALはテンプレート毎、さらにphptal:cacheが使われたタグ毎にファイルを生成します。 なお、マクロに対しては生成しません(単純に、PHP関数としてコンパイルされるだけです)。
これらのファイルは時々自動的にクリーンアップされます。
明確には、コンパイルされたテンプレートファイルは、setCachePurgeFrequency()メソッドによってコントロールされる確率に従い、setCacheLifetime()によって設定されているよりも古いものが削除されます。
古いファイルを消すようなスクリプトをスケジュールしておくこともできます。
find /tmp/ -name tpl_* ( -atime +1 -o -mtime +14 ) -exec rm -v {} ;

Useful links


謝辞


Big thanks goes to: