たった2行で外部ライブラリも使わずにPHPだけでテンプレートを実現する

 PHPの基本機能だけでテンプレートっぽいことを実現します。
 使用するPHPの関数は、file_get_contents ()とprintf ()だけです。

この手法のメリットとしては主にこのようなものがあります。
・ページ本体のソースが読みやすくなる
・テンプレート化した部分を、他のページで使いまわすことができる

テンプレートエンジンを使わないことには以下のようなメリットがあります。
・素のhtmlに近い形で書けるようになり、読み書きが楽になる
・導入の手間がかからない
・新しくテンプレートエンジンの文法を覚えなくてよい
・余計な不具合を持ち込まずに済む
・不具合が起きても、仕組みが単純なので原因特定が容易

もちろんデメリットもあります。あまり複雑なことができません。

いろいろ工夫はできますが、もう少し複雑になったら、テンプレートエンジンか別の手を検討すべきです。しかし、ちょっとしたWebページなら、わざわざ追加のライブラリを加えて仕組みを複雑にすることは避けるべきだと思います。

個人的な事情として、「漏れのある抽象化の法則」(Joel on Software)に則って、必要な知識が身につくまでは、ライブラリの導入は避けて素のhtml+phpを使おうという方針の問題もあります。



実際の記述

読みこむ側が、file_get_contents ()でテンプレートを変数に読み込みます。
printf ()にテンプレートを渡せばokです。
例:
        $srcStr = file_get_contents("imgarea_templete.html");
        printf ( $srcStr, $imgUrl, basename($imgUrl));


テンプレートファイルの中身はこんな感じです。
例:(imgarea_templete.html)
    <div class="imgarea">
        <img src="%s" width=200 align=left><br>
        画像についてメモする<br>
           
            <textarea></textarea>
           
        <Br clear="left">%s
    </div>
    <br><br>

どう見ても、単なるprintf ()関数の第一引数ですね。
ダブルクオーテーション(")をバックスラッシュ(\)でエスケープしなくて済むのも良いです。


私はforループの内部で使っています。
これでfor文の中がかなりすっきりします。
例:
        $srcStr = file_get_contents("imgarea_templete.php");        for ($i = 0; $i < 10 ; $i++ ){
            $imgIndex = ($page-1)*10 +$i;
            if ("" != ($imgUrl = imgUrlfromNum($imgIndex, $imgArray))){
                printf ( $srcStr, $imgUrl, basename($imgUrl));
            }else{
                break;
            }
        }

おまけ:テンプレート化までの過程

ちなみに発展の過程はだいたい以下の順序です。

(1)とりあえずprint関数が並んでいる
例:
    print '<img src=". $imgUrl .">';
    print '<br><br>';

(2)ごちゃごちゃしはじめる
ブラウザ側のHTMLソースを見ながらデバッグするので、改行やタブを入れておかないと読みづらいです。でも、改行やタブを入れると、サーバ側ソースのPHP文が汚くなっていきます。
例:
    print "\t" . '<img src="' . $imgUrl . '"><br>' . "\n";
    print '<br>' . "\n";

ちなみに、HTMLソースはダブルクオーテーション(")を多用する性質があります。
そのため、シングルクオーテーションで囲む記法のダブルクオーテーションを含むHTMLソースの書きやすさと、ダブルクオーテーション囲む記法で使える書式文字による改行やタブの利便性は、トレードオフの関係になります。
例:
    print "\t" . '<img src="' . $imgUrl . '" width="300" ><br>' . "\n";
    print "\t<img src=\"" . $imgUrl . "\" width=\"300\" ><br>\n";

(3)行数が増えていく
ページが作成が進むほど、html文が長くなっていきます。
例:
    print "\t" . '<img src="' . $imgUrl . '"><br>' . "\n";
    print "\t<textarea></textarea><br>\n";
    print '<br>' . "\n";

実際にはさらに<div>タグやalign要素などが増えていきます。
このあたりで、将来的にリンク<a href>や送信フォーム<form>も追加する必要があるなぁ、毎回print関数とタブと改行を連結させるコードを書くのは大変だなぁ、と気づきます。

(4)printを一つにまとめる
これまで一行ごとにprint関数を呼んでいましたが、行数が増えたらまとめられることに気づきます。
例:
    print  "<div>\n".
    "\t<img src=\"". $imgUrl . "\">\n".
    print  "</div>\n".
なお、phpのソース中で文字列を改行して折り返す場合、2つの方法があります。
1.行をまたいで文字列を連結する
    "<div>\n".
    "</div>\n";
2. 文字列中で改行する
    "<div>\n
    </div>\n";
(5)printf文が登場
ところで、ここまでのprint文は、実のところfor文の中に入っていました(唐突ですが)。for文の中はすっきりしていたほうが読みやすいです。
複数行の文字列をまとめると、 変数に格納することができるようになります。そうはいっても、ファイル名などの部分は置換しなければならないので、変数に書式文字列を格納してprintf関数を使うという形になります。
例:
    $str = "<div>\n".
    "\t<img src=\"%s\">\n".
    "</div>\n";
    for($i=0;$i < 10; $i++){
      printf ($str, $arg[$i]);
    }

(6)外部ファイル化
冒頭の例になる、というわけです。


テンプレートは素のhtml文に近いほうが読みやすいし書きやすいです。そして簡単に置換ができるのが良いテンプレートだと思います。




記事タイトルがライフハック系エントリみたいですね...。

追記:
初めてのPHPを読んでいたのですが、str_replace() すごい便利そうですね。
どうして検索で引っかからなかったんだろう。

このブログの人気の投稿

Ubuntu13.04で使える動画編集ソフト一覧

squid3プロキシサーバの設定(Ubuntu13.10)

ubuntu13.04で無線LANが繋がらない場合の対処