Subscribed unsubscribe Subscribe Subscribe

PHPスクリプトでテンプレートの継承できたよ\(^o^)/

追記: 一部文字を実体参照化してなかったのを修正。typo修正。

タイトルは若干 (というかかなり) 釣り。改造したPHPでテンプレートの継承 (もどき) をできるようにしてみた。ローカル変数が受け継がれないとか、まだまだ実用には耐えられるものではないので、だれかforkして進化させてね!(というかここまでで飽きた)

試すには、この記事の末尾に貼ってあるパッチを5.3のCVS版に当てて、ビルドする。bisonとかre2cとか入ってないとうまくいかないと思う。

さて、

<html>
<head>
  <title><?php declare(block="title"): ?>default title<?php enddeclare ?></title>
</head>
<body>
  <?php declare(block="body"): ?>
default body
  <?php enddeclare ?>
</body>
</html>

このようなテンプレート (test1.php) を実行 (テンプレートを実行って変だけどPHPだし...) すると、

<html>
<head>
  <title>default title</title>
</head>
<body>
  default body
  </body>
</html>

こんな結果になり、次のテンプレート (test2.php) を実行すると、

<?php declare(extended=1); ?>
<?php declare(block="title"): ?>overridden<?php enddeclare ?>
<?php include('/tmp/test1.php'); ?>

こうなる。

<html>
<head>
  <title>overridden</title>
</head>
<body>
  default body
  </body>
</html>

まともに使えるようになったら、ちょっと便利そうな気はする。PHP書かないんだけど。

仕組みとしては、

  1. <?php declare(block="xxx"): ?> から <?php enddeclare ?> で囲まれた箇所をクロージャとして関数定義して、$__block__[ブロック名] という変数に突っ込む。
  2. もし同名の変数にすでに値が入っていたら 1. の処理はスキップする。
  3. <?php declare(extended=1); ?> がスクリプト中にない限り $__block__[ブロック名] で指定された関数を呼び出す。

ということをやっているだけっす。