YiiFrameworkでPHPTALしてみた

PHPTALやってみようかと思ったので、YiiFrameworkで動くPHPTALViewRenderer作ってみた。

インストール

PHPTAL

phptalとかgithubからzipをダウンロードし解凍し、classes ディレクトリ下の PHPTALディレクトリと PHPTAL.phpを prorected/vendor/PHPTAL へコピーする。

PHPTALViewRenderer

次をコピペする。ETwigViewRenderer を参考に作成しました。
prorected/extension/PHPTALViewRenderer.php

<?php
class PHPTALViewRenderer extends CApplicationComponent implements IViewRenderer
{
    /**
     * @var string Path alias to PHPTAL.php
     */
    public $PHPTALPathAlias = 'application.vendors.PHPTAL';

    /**
     * @var string Template files extension
     */
    public $fileExtension = '.html';

    private $_basePath;
    private $_basePathLength;
    
    function init()
    {
        require_once Yii::getPathOfAlias($this->PHPTALPathAlias).'/PHPTAL.php';
        Yii::registerAutoloader(array('PHPTAL', 'autoloadRegister'), true); 

        $app = Yii::app();

        /** @var $theme CTheme */
        $theme = $app->getTheme();

        if ($theme === null) {
            $this->_basePath = $app->getBasePath();
        } else {
            $this->_basePath = $theme->getBasePath();
        }

        $this->_basePathLength = strlen($this->_basePath) ;
        
        return parent::init();
    }
    
    public function renderFile($context, $sourceFile, $data, $return)
    {
        $sourceFile = "protected/".substr($sourceFile, $this->_basePathLength);

        $phptal = new PHPTAL($sourceFile);

        $phptal->this = $context;
        foreach($data as $key => $val) {
            $phptal->$key = $val;
        }
        
        $result = $phptal->execute();

        if ($return) {
            return $result;
        }
        echo $result;
    }
}
設定

PHPTALViewRenderer を設定
prorected/config/main.php

    'components'=>array(
        'viewRenderer'=>array(
            'class'=>'ext.PHPTALViewRenderer',
            'fileExtension' => '.html',
        ),

PHPTALのサンプルを試す

コントローラー

PHPTALのサンプルのパクリ。Personクラス作るのが面倒なので(object)で代用。
protected/controllers/TestController.php

<?php
class TestController extends Controller
{
    public $layout='column1';

    public function actionIndex()
    {
        $title = 'The title value';

        $people = array();
        $people[] = (object)array("name"=>"foo", "phone"=>"01-344-121-021");
        $people[] = (object)array("name"=>"bar", "phone"=>"05-999-165-541");
        $people[] = (object)array("name"=>"baz", "phone"=>"01-389-321-024");
        $people[] = (object)array("name"=>"quz", "phone"=>"05-321-378-654");

        $this->render('index', compact('title', 'people'));
    }
}
ビュー

PHPTALのサンプルそのまんま。
protected/views/test/index.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>

layouts/main.php, layouts/column1.php はとりあえずそのまんま使う。

結果

f:id:tjtjtjofthedead:20120404212858p:image:w640

得られたhtmlの一部

layouts/main.php, layouts/column1.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を学ばなきゃ
  • CWebUserへのアクセスは $template->user = Yii::app()->user; とすれば可能
  • layouts/main.php, layouts/column1.php をどうにかする
  • renderPartialは macroを使うのかな
  • formatterはモディファイアに組み込むのかな
  • yii::t()は PHPTAL_TranslationService に組み込むのかな
  • フラグメントキャッシュは PHPTAL_Trigger を使って実現するのかな

次は TAL-way じゃないのでサポートしなくていいよね