翻訳: PHPTALでテンプレーティング

http://phptal.org/ のニュース中のリンクで見つけたのですが、PHPTALに関する良い記事がありました。

http://inside.webfactory.de/en/blog/templating-with-phptal-dont-make-your-designer-think-about-the-wrong-things.html

PHPTALのいいとことろを紹介するうえで、実体験としてすごくいい証拠になると思ったので、翻訳してみました。英語の感覚でだらっと長文を書く文体(ちょうど自分が日本語でだらっと長く書くように)のブログ記事だったので、機械的で厳密な翻訳はできませんでしたが、気持ちはすごく伝わると思います。

PHPTALでテンプレーティング:きみの隣のデザイナーを(間違ったものについて)考え込ませないように

我々のテンプレーティング戦略の歴史

我々の何人かがPHPを使って動的なWebサイトを生み出し始めたあの頃、XHTML出力をこんなふうに生成することが多かったでしょう、つまり、ブログのポストっていうとこんな感じで。

<?php 
    <div class="blog-post"> 
        <h1><?php print htmlspecialchars($post->getTitel()); ?></h1> 
        <?php 
            $image = $post->getFirstImage(); 
            if ($image) require_once('draw-image.php'); 
        ?> 
        <div class="text"> 
            <?php print $post->getTeaser(); ?> 
            <a href="<?php print $urlProvider->getUrl($post); ?>"> 
                Read more 
            </a> 
        </div> 
        <ul class="categories"> 
        <?php foreach ($post->getCategories() as $category) { ?> 
            <li> 
                <?php print htmlspecialchars($category->getName()); ?> 
            </li> 
        <?php } ?> 
        </ul> 
    </div> 
?>

このテンプレート記述方法は、エラーになりやすいものでした。また、ちょっとタグを閉じ忘れたり、属性のスペルミスをしたりが、簡単に起こってしまいます。手持ちのエディタは、この問題を識別するのに役に立ちませんでした。というのも、エディタはPHPコードを編集していると思ってて、PHPタグの外のテキストがどうなってるかなんてヒントは、何ひとつ与えてくれないし、じゃあXHTML編集にしたら、膨大なエディタエラーになってしまうのです。XHTMLにはみたいなものないよ、って。なので我々はしょっちゅう、well-formedじゃないXHTMLを生成しました。また常に、制御不能なユーザコンテンツという悪意ある世界から訪れる値に対して、クロスサイトスクリプトやそういったものを防ぐために、「htmlspecialchars」の適用を忘れてはいけませんでした。我々開発者は、書くということについては本質的に怠け者で、よくエスケープをすっぽかします。その値はたぶん、我々の顧客のCMSや、隣にいる善良な開発者のような、より安全な場所から来るものだとみなしてしまって。おいおい、その人がはっきりとそう言わないかぎり、よく整形されて有効な内容を与えられても、決して誰も信用しちゃだめなんだってば!

webfactoryの我々がオブジェクト指向コードを書くPHP開発者集団と化したとき、抽象レイヤーによってこの問題を解くことは、まったくもって有意義でした。そして我々は、XHTMLタグや似たようなあらゆるものを、定義してはぶら下げる、オブジェクト指向ツールを発明しました。その例として、これは、我々が書くときどんなふうにするかです:

<?php 
    class BlogPostView { 
        public function build(Post $post, wfXHTMLTagNode $container) { 
            $postDiv = $container->insert('<div>')->addClass('blog-post'); 
            $postDiv->insert('<h1>')->text($post->getTitle()); 
 
            $imageView = new ImageView($post->getFirstImage()); 
            $imageView->build($postDiv); 
             
            $textDiv = $postDiv->insert('<div>')->addClass('text'); 
            $textDiv->insertFragment($post->getText()); 
            $textDiv 
                ->insert('<a>', array( 
                    'href' => $urlProvider->getUrl($post) 
                ))->text('Read more'); 
             
            $categoryUl = $postDiv->insert('<ul>'); 
            foreach ($post->getCategories() as $category) { 
                $categoryUl->insert('<li>')->text($category->getName()); 
            } 
        } 
    } 
 ?>

これで、我々の前の問題は解消されました: ネスティングはフェイルセーフで、出力結果に挿入される内容は、与えられる文字列がwell-formedで有効なXHTMLであることを保証しなきゃいけない、"insertFragment"メソッドを明示的に使わなければ、すべてエスケープされます。

デザイナーがやってきて

ここ数年で我々は、単純だけどきわめて重要なある種の事実を認識しました: 良いWebサイトを作るということは、ユーザのニーズを理解することただそれのみです! あなたのユーザは、あなたがソフトウェアにどの抽象レイヤーを導入したかも、どのデータベースインデックスを最適化したかも、あなたが使ったプログラム言語やフレームワークでさえも、気にしません。彼は、Webサイトが綺麗に見えるか、探したいコンテンツが見つかるか、彼の現在の目的に答えを得るため、クリックしたくなる、または、サイトがどうなるか理解できるようなボタンが見当たるかどうか、を気に留めています。

この考え方の変化は、チームで初めての非PHP開発者であり、今日のアートディレクターである、S0renの話を聞いたときから始まりました。彼は、ユーザを無視するようなギークの年寄り集団とともに行動するうえで、正しい頑固さのようなものを持っていました。「あー、きみの新しいパーフェクトフォームハンドリングシステムで、あるフォームフィールドに隣接して画像を置くことが不可能かどうかなんて、僕にはどうでもいいんだ。で、このフォームを使うであろうプアな人にはそんなのできっこないよ! これだともっとわかりやすい! そう、それはそこ、よろしく!」いま我々は、我々のデザイナーたちが欲しがっている、コンテンツでも機能性でも何でも、彼らが得られるようにするために、絶えず努力しています。彼らの「ユーザインターフェース体験」を最大限に引き出すために。

これは、あなたのソフトウェアが適正に効果を示すかどうかの分岐点です。ここで私は、モデル・ビュー・コントローラというシンプルなアイデアを採用しようとしています。このねらいを達成して、デザイナーと開発者の間で依存量を減らすのに、我々の考えていることは最高です。それは、まず最初にビュー部分のあらゆる側面に気を配っておいて、あとでモデルとコントローラ部分に気を配ることです。そして、たとえていえば、ポストが何でどのようにそのコンテンツが永続化層からロードされるかということ(モデル)、ならびに、正しいワークフローを始めるために、ポストの詳細ページの正しいURLが何であるかと、URLの解釈上それが何を意味するかを見つけ出すこと(コントローラ)、が、開発者の責任の範囲になります。

この"public"ナントカはどういう意味だったっけ?

我々の現行のテンプレーティング手法に潜む問題は、それがPHPだということ、それがオブジェクト指向だということ、それがXHTMLのような見た目からかけ離れているということです。いまのところビューを書くということは、クラスとは何かを理解することを意味します。さらに悪いことに、もしビューのパーツを再利用したいときは、他のビューからどうやって継承するかとか、どうやって与えられたクラスをインスタンス化するかを、知らないといけません。どのようなメッド群があり、アクセス制御子が何をするか、知らないといけません。変数のこと、どうやってオブジェクトのメソッドを呼び出すかということ、ループやそれに類するものがモダンなプログラム言語の中でどうはたらくか、認識することができないといけません。

このような多くの事は、まったくデザイナーが理解する必要はないことですね。認識するうえで余計な負荷が多くかかってしまい、彼の日々の仕事に負担をかけます。

そして再び後戻りして、我々の新旧の要求に合うテンプレーティングの、より良い方法を探してみました。

PHPTAL

しばらくの評価してみて、我々はすっかりPHPTALのとりこになりました。それは、Zopeのテンプレーティングの発明であるTALのPHPポートです。TALのアイデアの新しいところは、独自の構文( のような)を導入せず、アクション記述を名前空間つきのXML属性に移動した点です。したがって、TALのテンプレートは完全にwell-formedで、かつ、拡張XHTML-DTDを使った場合、バリッドでさえあるのです。拡張XHTML-DTDを使うと、すべてのTALタグと属性に、コード補完を提供することだってできます。

そして今、我々はデザイナーの世界に戻っています:

<?xml version="1.0"?> 
<!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" 
    xmlns:tal="http://xml.zope.org/namespaces/tal" 
    xmlns:metal="http://xml.zope.org/namespaces/metal"> 
    <head> 
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> 
        <title>This is a blog post template</title> 
    </head> 
    <body> 
        <div class="blog-post" metal:define-macro="blogpost"> 
            <h1 tal:content="post/getTitle">This is an example title</h1> 
            <tal:block 
                tal:define="image post/getFirstImage" 
                tal:condition="image" 
                metal:use-macro="reusable-snippets.html/image"> 
                <img src="test.jpg" alt="this is an example image" /> 
            </tal:block> 
            <div class="text"> 
                <tal:block tal:content="structure post/getTeaser"> 
                    This is an example teaser. 
                </tal:block> 
                <a tal:attributes="href wf-controller:postDetail post"> 
                    Read more 
                </a> 
            </div> 
            <ul class="categories"> 
                <li 
                    tal:repeat="category post/getCategories" 
                    tal:content="category/getName"> 
                    Example-Category 
                </li> 
            </ul> 
        </div> 
    </body> 
</html>

これで我々の問題はすべて解決した? すでに述べたように、上記で目にするものは、絶対的にwell-formedなXHTMLです。だから、あなたが構文エラーを入れ込まないかぎり、いいエディタならまず、警告を発しないことでしょう。

エスケープについてはどう? 出力結果中にレンダリングされるモデルの単値はみんな、"structure"キーワードをつけてそうしないように言わないかぎり、PHPTALによって適切にエスケープされるでしょう。というわけで、またサボればいいよ。

デザイナーにとって理解しにくい? まあ、プロのデザイナーなら誰でも、XHTMLが何かは知ってるはずですね。彼はXML名前空間も知っているはず。彼が学ばなければいけないものは、TALを離れたところにある文法です。でも上記のテンプレート、これはすでに、TALによって導入された属性が約6割に及びます。だから、モダンなオプジェクト指向プログラム言語と比べたら、何でもないですね。それはプレゼンテーション上のアクションと対応するコンセプト(条件つき出力、繰り返し出力、出力置換、コンテンツで穴埋めして出力...)も導入します。だから、デザイナーはそれを簡単に理解できるはずです。

ブログ記事の例では、出力スニペット再利用やレイアウト定義をフォルダとファイルに構成できる強力なツールを、PHPTALが提供していることも、例示しています。それらのスニペットやレイアウトのそれぞれは、(我々のブログ記事テンプレートのように)完全なXHTMLページです。PHPTALを使うと、マークアップ中に出力例を置くことができるので、ファイルを何かのブラウザで開けば、出力が実際にどう見えるかわかります。さらにいうとそれは、サーバやPHPインタプリタの実行なしで可能なんです。これは、再利用可能なビューコンポーネントの効果的なテスト方法を示していると、私は思います。ここで私は、OOCSSに言及したいところです...

いっぽうで、PHPTALは、入力と出力を高度なレベルで取り扱う、キャッシング、国際化、プレ/ポストフィルタのようなものとも、うまくやれます。それを説明しようとすると、私の記事量が間違いなく吹っ飛んでしまうので、PHPTALのWebサイトを訪れて、そのドキュメントに目を通してください。余談ですが、ドキュメントはとても明解で完全です。

私は現在、XHTML要素と属性セットを合理的に拡張する、PHPTAL-DTDに取り組んでいます。それが完了してダウンロードできるようになったらすぐに、記事を書くつもりです。

いつものように、皆さんにちゃんとしたコメントを残してもらえたら幸いです!

実体験として、これだけデザイナーフレンドリだという声があるなら、Smartyのネームブランドの安心はあくまで、開発者だけで共有することにして、彼らが体験した具体的なメリットを、むしろデザイナーと共有するために、PHPTALを選択するのは、妥当といえるんじゃないでしょうか。あ、彼の文体っぽくなっちゃった。