ホームページ >php教程 >php手册 >テンプレートエンジンを超えて

テンプレートエンジンを超えて

WBOY
WBOYオリジナル
2016-06-21 09:14:491329ブラウズ

テンプレート

全体として、テンプレート エンジンは「良いもの」です

PHP/Perl プログラマーとして、多くのテンプレート エンジン (fastTemplate、Smarty、Perl の HTML::Template) だけでなく、私自身のテンプレート エンジン (bTemplate[1] (著者) )、何度も言いました。

しかし、同僚との長い議論の結果、多くのテンプレート エンジン (私自身が作成したものを含む) が単に間違っていると確信するようになりました。 唯一の例外は Smarty[2] だと思いますが、この記事の残りの部分を考慮すると、あまりにもかさばりすぎてまったく無意味だと思います。ただし、Smarty (または同様のソリューション) を選択する必要がある理由はいくつかあります。これについては、この記事で後ほど説明します。

この記事では、テンプレートの理論について説明します。ほとんどの「テンプレート エンジン」が太すぎる理由を確認し、最終的には軽量、小型、高速な代替エンジンを検討します。



ダウンロードとライセンス
この記事で使用されているテンプレート クラスとすべての例は、ここからダウンロードできます: template.zip [3]。これらのファイルのコードは、OSI [5] の下でリリースされた MIT オープンソース ライセンス [4] に基づいて使用できます。



テンプレート エンジンに関する背景知識
まず、テンプレート エンジンに関する背景知識を勉強しましょう。テンプレート エンジンは、ビジネス ロジック (データベースからのデータの取得や貿易コストの計算など) をデータの表示から分離するように設計されています。テンプレート エンジンは、次の 2 つの主要な問題を解決します:


この分離を実現する方法
「複雑な」PHP コードを HTML から分離する方法

これにより、理論的には、PHP の経験のない HTML デザイナーでも、PHP コードを見ずにこれを行うことができます 条件に応じて、サイト。

ただし、テンプレート システムには多少の複雑さも伴います。まず、複数のファイルから派生した「ページ」ができました。通常、ビジネス ロジックを担当するメインの PHP ページ、サイト全体の全体的なレイアウトをレンダリングする外側の「レイアウト」テンプレート、内側のコンテンツ固有のテンプレート、データベース抽象化レイヤー、およびテンプレート エンジン自体 (これらは複数のファイルで構成されている場合もあれば、構成されていない場合もあります)。また、すべての PHP ページの最初と最後に単に「ヘッド」ファイルと「フッター」ファイルを含める人もいる可能性があります。

これにより 1 ページに対して生成されるファイルの数はかなりになります。ただし、PHP パーサーは非常に高速であるため、サイトのトラフィックが大量でない限り、使用されるファイルの数はそれほど重要ではない可能性があります。
ただし、テンプレート システムでは別のレベルの処理が導入されることに注意してください。テンプレート ファイルはインクルードするだけでなく、解析する必要もあります (テンプレート システムに応じて、正規表現、文字列置換、コンパイル、字句解析など、さまざまな方法でこれを実行できます)。これが、テンプレートの速度テストが人気になっている理由です。テンプレート エンジンはさまざまな方法を使用してデータを解析するため、一部のエンジンは他のエンジンよりも高速です (また、一部のテンプレート エンジンは他のエンジンよりも豊富な機能を提供します)。



テンプレート エンジンの基本
簡単に言えば、テンプレート エンジンは C で書かれたスクリプト言語 (PHP) を利用します。これらの埋め込みスクリプト言語内には、別の疑似スクリプト言語 (テンプレート エンジンがサポートするタグは何でも) があります。単純な変数のオーバーライドとループを提供するものもあります。条件付きループやネストされたループを提供するものもあります。他のもの (少なくとも Smarty) は、バッファ層だけでなく、PHP の比較的大きなサブセットへのインターフェイスを提供します。

Smarty が正しい方向に最も近いと思うのはなぜですか?なぜなら、Smarty の目標は「PHP コードと HTML コードを分離する」ことではなく、「ビジネス ロジックをパフォーマンスから分離する」ことだからです。これは大きな違いのように思えないかもしれませんが、まさに重要な点です。テンプレート エンジンの最終的な目標は、HTML からすべてのロジックを削除することではありません。プレゼンテーション ロジックをビジネス ロジックから分離する必要があります。

データを正しく表示するためのロジックだけが必要な例はたくさんあります。たとえば、ビジネス ロジックはデータベースからユーザーのリストを取得することです。パフォーマンス ロジックでは、ユーザー リストを 3 列で表示する場合があります。おそらく、ユーザー リスト関数を変更して 3 つの配列を返すようにするのは愚かな考えかもしれません。結局のところ、関数はデータを次にどうするかについて気にすべきではありません。ただし、テンプレート ファイルにはいくつかのロジックが欠落しており、それがまさにあなたがやりたいことです。

Smarty はこれについては正しい (PHP の多くの機能を利用できるようにする) が、まだ多くの問題があります。基本的には、新しい構文を使用して PHP へのインターフェイスを提供するだけです。そこから始めると、あまりスマートには見えません。実際には < foreach --args ?> よりも {foreach --args} を書くほうが簡単ではないでしょうか?これが簡単だと思う場合は、巨大なテンプレート ライブラリを含める場合に、この分離の本当の意味を理解するのが簡単かどうかを自問してください。確かに、Smarty は他にも多くの優れた機能を提供しますが、これらの利点は、Smarty クラス ライブラリを含める負担なしで得られるようです。



別の解決策
私が主に提唱している解決策の 1 つは、PHP コードをネイティブ スクリプト言語として使用する「テンプレート エンジン」です。これは以前にも行われたことは知っています。最初に見たときは、「なぜこんなことをするの?」と思いましたが、同僚の議論を考慮した後、最終的な目的を分離したときに、PHP コードを使用してコードを直接実装しました。テンプレート システム (コメントを除いて、コードはわずか 25 行しかかかりません) を使用して、その利点を実感しました。

このシステムにより、私たちのような開発者は、出力の書式設定に使用できるコアの PHP 関数にアクセスできるようになります。日付の書式設定などのタスクはテンプレートで処理する必要があります。さらに、テンプレートは通常の PHP ファイルであるため、Zend Performance Suite [6] や PHP Accelerator [7] のようなバイトコード キャッシュ プログラムはテンプレートを自動的にキャッシュできます (したがって、アクセスするたびにテンプレートを更新する必要はありません)。 。これは、プログラムが PHP ファイルとして認識できるような名前をテンプレート ファイルに付けることを忘れない限り、大きな利点です (通常は、ファイルに .php 接尾辞が付いていることを確認するだけで済みます)。

このアプローチは従来のテンプレート エンジンよりもはるかに優れていると思いますが、議論すべき問題がいくつかあることは確かです。最も明白な反論は、PHP コードは複雑すぎるため、設計者に PHP の学習を強制すべきではないというものです。実際、PHP コードの構文は、Smarty のような高度なテンプレート エンジンの構文と比べて (単純ではないにしても) ほぼ同じくらい単純です。さらに、設計者は のような PHP 略語を使用できます。これは {$var} よりもはるかに複雑ですか?もちろん、少し時間はかかりますが、慣れてしまえば、テンプレート ファイルを解析する手間をかけずに PHP のパワーを活用できるようになります。
2 番目に、そしておそらくより重要なことですが、PHP ベースのテンプレートには本質的なセキュリティがありません。 Smarty には、テンプレート ファイル内の PHP コードを完全に無効にするオプションが用意されています。これにより、開発者はテンプレートがアクセスできる関数と変数を制限できます。悪意のあるデザイナーがいない場合、これは問題にはなりません。ただし、外部ユーザーにテンプレートのアップロードまたは変更を許可すると、ここで示した PHP ベースのソリューションにはまったくセキュリティがありません。任意のコードをテンプレートに入力して実行できます。はい、print_r($GLOBALS) も可能です (これにより、悪意のあるユーザーがスクリプト内の任意の変数にアクセスできるようになります)。

ただし、私が個人的にまたは仕事で書いたプロジェクトのほとんどは、エンドユーザーがテンプレートを変更したりアップロードしたりすることを許可していません。そうであれば、問題は存在しません。それでは、コードを見てみましょう。




これは、単純なユーザーリストページの例です。

require_once('template.php');

/**
* この変数は、すべてのテンプレート ファイルへのファイル システム パスを保持します。
*/
$path = './templates/'
$tpl = & 新しいテンプレート($path);
$tpl->set('タイトル', 'ユーザーリスト');
$body = & 新しいテンプレート($path); $body->set('user_list', fetch_user_list());

/**
* 外側のテンプレートのテンプレート オブジェクトを作成し、その変数を設定します。
*/
$tpl->set('body', $body->fetch('user_list.tpl. php'));

/**
* 内部テンプレートのテンプレート オブジェクトを作成し、その変数を設定します。
* fetch_user_list() 関数は単にユーザーの配列を返します。
*/
echo $tpl->fetch('index.tpl.php');
?> 注目すべき重要な概念が 2 つあります。 1 つ目は、内部テンプレートと外部テンプレートの概念です。外部テンプレートには、サイトの主な外観と操作性を定義する HTML コードが含まれています。内部テンプレートには、サイトのコンテンツ領域を定義する HTML コードが含まれています。もちろん、任意の数のレイヤーに任意の数のテンプレートを含めることができます。通常、リージョンごとに異なるテンプレート オブジェクトを使用するため、名前空間の問題は発生しません。たとえば、競合を心配することなく、内部テンプレートと外部テンプレートの両方に「title」という変数を含めることができます。

これは、ユーザーのリストを表示するために使用されるテンプレートの簡単な例です。特殊な foreach と endforeach の構文については、PHP マニュアル [8] で説明されていることに注意してください。それは完全にオプションです。

また、なぜテンプレート ファイルの名前に .php 接尾辞を付けるのか疑問に思われるかもしれません。あはは、多くの PHP バイトコード キャッシュ ソリューション (phpAccelerator など) では、PHP ファイルとして認識されるためには、ファイルに .php 接尾辞が必要です。これらのテンプレートは PHP ファイルなので、これらの利点を活用してみてはいかがでしょうか?

ID
メール /th& gt ;








これは、ページ全体の外観を定義するテンプレート ファイルです。 ;head>

<?=$title;?> =$title;?></h2> > <br><br> </body> <br></html><br><br> そしてこれが解析された出力です。 <br><html> <br> <title>ユーザーリスト</head> <br><br> <h2>ユーザーリスト</h2> <br>& ; <br> </p> <tr> <br> <th> 名前 </th> <br> <th> 禁止されている </th> / tr> <br> <tr> <br> <td>bob</td> <br> <td><a href="mailto:bob@mozilla. org">bob@mozilla.org</a></td> <br> <td align="center"> </td> <br> </tr> <br> <tr> <br> <td align ="center">2</td> <br> <td>judy</td> <td><a href="mailto:judy@php.net">judy@php.net</a> ;</td> <br> </tr> <br> <td align="center"> ;td>ジョー</td> <br> <td><a href="mailto:joe@opera.com">joe@opera.com</a></td> <br> <td align= <br> <td> <td><billy@wakeside.com</a></td> X</td> <br> </tr> <br> <td>eileen</td> href="mailto:eileen@slashdot.org</a></td> <br> </tr> </table> <br> < ;/body> <br></html><br><br><br>キャッシュ<br> ソリューションは非常にシンプルなので、テンプレート キャッシュの実装は非常に簡単です。キャッシュを実装するには、元のテンプレート クラスを拡張する 2 番目のクラスを用意します。 CachedTemplate クラスは、実際には元のテンプレート クラスと同じ API を使用します。違いは、キャッシュ設定をコンストラクターに渡し、 fetch() の代わりに fetch_cache() を呼び出す必要があることです。 <br><br> キャッシュの概念はシンプルです。簡単に言えば、キャッシュ時間を設定して、テーブル出力を保存する時間 (秒単位) を調整します。ページを生成するすべての作業を実行する前に、まずページがキャッシュされているかどうか、およびキャッシュの有効期限が切れていないかどうかをテストする必要があります。あちこちにキャッシュされている場合、ページを生成するためにデータベースやビジネス ロジックを気にする必要はありません。元々キャッシュされていたコンテンツを出力するだけで済みます。 <br><br>この方法では、キャッシュ ファイルを一意に識別するという問題を解決する必要があります。サイトが GET 変数を公開する中央スクリプトによって制御されている場合、PHP ファイルごとにキャッシュが 1 つだけでは役に立ちません。たとえば、index.php?page=about_us が、ユーザーがindex.php?page=contact_us を呼び出したときとはまったく異なる方法で表示される場合です。 <br><br>この問題は、ページごとに一意のcache_idを生成することで解決されます。これを行うには、実際に要求されたファイルを REQUEST_URI (基本的に URL 全体:index.php?foo=bar&bar=foo) に変更します。もちろん、この変換プロセスは CachedTemplate クラスによって制御されますが、覚えておくべき重要なことは、CachedTemplate オブジェクトを作成するときに必ず一意の queue_id を渡す必要があるということです。もちろん、以下に例を挙げて説明します。 <br><br>キャッシュの使用には次の手順が含まれます。 <br><br><br>include() テンプレート ソース ファイル<br><br><br> 新しい CachedTemplate オブジェクトを作成します (そして、パス、一意のキャッシュ ID、キャッシュ有効期限をテンプレートに渡します)<br><br><br> コンテンツがキャッシュされているかどうかをテストします<br><br><br>それでも必要な場合それを取得するには、ファイルを表示してスクリプトを終了します <br><br><br> それ以外の場合は、すべての処理と fetch() テンプレートを実行します <br><br><br> fetch_cache() の呼び出しにより、新しいキャッシュ ファイルが自動的に生成されます <br><br> このスクリプトは、キャッシュ ファイルは ./cache/ に配置されるため、そのディレクトリを作成し、Web サーバーがファイルを書き込めるようにそのディレクトリのアクセス許可 (chmod) を変更する必要があります。また、スクリプトの作成中にエラーが見つかった場合、そのエラーもキャッシュされることに注意してください。したがって、開発中はキャッシュを無効にすることをお勧めします。最善の方法は、キャッシュの有効期間に 0 を渡すことです。この方法では、キャッシュは常にすぐに期限切れになります。 <br><br>これは実際のキャッシュの例です。 <br><br><?php <br/>/**<br/>* キャッシュされたテンプレートの使用例。 <br/>* 複数のファイルやデータベースから情報を取得していないため、速度は向上しませんが、 <br/>* is_cached() メソッドがどのように動作するかを紹介します。 <br/>*/ <br/><br/>/**<br/>* まず、テンプレートクラスをインクルードします。 <br/>*/ <br/>require_once('template.php'); <br/><br/>/**<br/>* これはテンプレートへのパスです。 <br/>*/ <br/>$path = ' ./templates/'; <br/><br/>/**<br/>* このページに使用するテンプレート ファイルを定義します。 <br/>*/ <br/>$file = 'list.tpl.php'; <br/><br/>/**<br/>* キャッシュするテンプレートの一意の文字列を渡します。 テンプレート <br/>* ファイル名 + サーバー REQUEST_URI は次の理由から良い選択です: <br/>* 1. ファイル名だけを渡す場合、再利用されるテンプレートはすべて <br/>* 同じキャッシュを取得します。 これは望ましい動作ではありません。 <br/>* 2. REQUEST_URI を渡すだけで、ページごとに複数の <br/>* テンプレートを使用している場合、テンプレートは完全に <br/>* 異なっていても、キャッシュ ファイルを共有します (キャッシュ ファイル名は <br/>* に基づいています)渡されたcache_id <br/>*/ <br/>$cache_id = $_SERVER['REQUEST_URI] ']; <br/>$tpl = & new CachedTemplate($path, $cache_id, 900); <br/><br/>/**<br/>* テンプレートがキャッシュされているかどうかをテストします。 存在する場合、<br/>* 処理を行う必要はありません。 したがって、ここで <br/>* に大量の db 呼び出し (またはファイルの読み取り、またはプロセッサ/ディスク/db に負荷がかかるもの) を入れると、<br/>* ページが <br/>* 処理するのにかかる時間が大幅に削減されます。 <br/>* <br/>* これは「If NOT Is_Cached」と読み上げてください <br/>*/ <br/>if(!($tpl->is_cached())) { <br> $tpl- >set('タイトル', '私のタイトル'); <br> $tpl->set('イントロ', 'イントロ段落。'); <br> $tpl->set('リスト', array('cat) ', 'dog', 'mouse')); <br>} <br><br>/**<br>* キャッシュされたテンプレートを取得します。 is_cached() が成功するか<br>* か失敗するかは関係ありません。 fetch_cache() はキャッシュが存在する場合はフェッチしますが、存在しない場合は <br>* 解析して通常どおりテンプレートを返します (そして、次に <br>* のキャッシュを作成します)時間)。 <br>*/ <br>echo $tpl->fetch_cache($file) <br>?><br><br><br> 複数の変数を設定する<br>us複数の変数を同時に設定できますか?これは、Ricardo Garcia が提供した関数を使用した別の例です。 <br><br><?php <br/>require_once('template.php'); <br/><br/>$tpl = & new Template('./templates/'); <br/>$tpl->set('title', 'ユーザープロファイル') ; <br><br>$profile = array(<br> '名前' => 'フランク', <br> 'メール' => 'frank@bob.com', <br> 'パスワード' => 'ultra_secret' <br><br>$); tpl->set_vars($profile); <br><br>echo $tpl->fetch('profile.tpl.php'); <br>?> <br>関連するテンプレートは次のとおりです: <br><br><table cellpadding="3 " border="0" cellpacing="1"> <br> <tr> <br> <td>名前</td> <br> <td><?=$name;?></td> <br> < <br> <tr> <br> <td>メール</td> <br> </tr> <br> <td> ;Password</td> <br> <td><?=$password;?></tr> <br></table> <br><br><table cellpadding="3" border="0" cellpacing="1"> <br> <td>名前</td> <br> </tr> ; <br> <tr> <br> <td>frank@bob.com</td> <br> <td> ;/td&g t ; <br> <td>ultra_secret</td> <br> </tr> <br></table><br> この記事への貢献に感謝します。 <br><br><br><br>関連リンク<br>ここでは、テンプレート エンジン全般について調べるのに適した場所のリストを示します。 <br><br><br>Web アプリケーション ツールキット テンプレート ビュー [9] - テンプレートの実装方法に関する多くの情報 <br>MVC パターン [10] - 3 層アプリケーションの設計について説明 <br>SimpleT [11] - PEAR::Cache_Lite を使用する別の php ベースのものテンプレート エンジン <br>テンプレートとテンプレート エンジン [12] - さまざまなテンプレート実装に関する詳細情報 <br>Smarty [13] - コンパイルされたテンプレート エンジン <br><br><br><br>テンプレート クラスのソース コード <br>、そして最後にテンプレート クラス。 <br><br><?php <br/>/**<br/>* Copyright (c) 2003 Brian E. Lozier (brian@massassi.net) <br/>* <br/>* set_vars() メソッドは Ricardo Garcia によって寄稿されました (感謝!) <br/>* <br/>* 許可は、ここに誰にでも無料で与えられますこのソフトウェアおよび関連ドキュメント ファイル (「ソフトウェア」) のコピー <br/>* を取得し、使用、コピー、変更、マージ、公開、配布、サブライセンスする <br/>* 権利を含む、制限なくソフトウェアを <br/>* 取り扱うこと、および/または <br/>* ソフトウェアのコピーを販売し、以下の条件に従って <br/>* ソフトウェアが提供された人にそのコピーを許可する: <br/>* <br/>* 上記の著作権表示とこの許可通知は、 <br/>* ソフトウェアのすべてのコピーまたは重要な部分。 <br/>* <br/>* ソフトウェアは「現状のまま」で提供され、明示または黙示を問わず、商品性、<br/>* 特定目的への適合性、および権利侵害のないことの保証を含むがこれらに限定されない、いかなる種類の保証もありません。いかなる場合においても、<br/>* 作者または著作権所有者は、契約行為、不法行為、またはその他の行為であるかどうかにかかわらず、本ソフトウェアまたはソフトウェアまたはそれに関連して <br/>* から生じるいかなる請求、損害、その他の <br/>* 責任に対しても責任を負わないものとします。ソフトウェア内での使用またはその他の取引 <br/>*。 <br/>*/ <br/><br/>class Template { <br/> var $vars; /// すべてのテンプレート変数を保持します <br/> var $path; /// テンプレートへのパス <br/><br/> /** <br/> * コンストラクター <br/> * <br/> * @param string $path テンプレートへのパス <br/> * <br/> * @return void <br/>*/ <br/> 関数 Template($path = null) { <br/> $this->path = $path; <br/> $this->vars = array(); <br/><br/> /**<br/> * テンプレートファイルへのパスを設定します。 <br/> * <br/> * @param string $path テンプレート ファイルへのパス <br/> * <br/> * @return void <br/>*/ <br/> function set_path($path) { <br/> $this->path = $path; <br/> } <br/><br/> /**<br/> * テンプレート変数を設定します。 <br/> * <br/> * @param string $name 設定する変数の名前 <br/> * @parammixed $value 変数の値 <br/> * <br/> * @return void <br/>*/ <br/> function set($name, $value) { <br/> $this->vars[ $name] = $value; <br/> } <br/><br/> /**<br/> * 連想配列を使用して一度に多数の変数を設定します。 <br/> * <br/> * @param array $vars 設定する変数の配列 <br/> * @param bool $clear 既存の変数を完全に上書きするかどうか <br/> * <br/> * @return void <br/>*/ <br/> function set_vars($vars, $clear = false) { <br/> if($clear) { <br/> $this->vars = $vars; <br/> } <br/> else { <br/> if(is_array($vars)) $this->vars = array_merge($this->vars, $vars); <br/> } <br/> } <br/><br/> /**<br/> * テンプレート ファイルを開いて解析し、返します。 <br/> * <br/> * @param string string テンプレート ファイル名 <br/> * <br/> * @return string <br/>*/ <br/> 関数fetch($file) { <br/> extract($this->vars); // vars をローカル名前空間に抽出します <br/> ob_start() // 出力バッファリングを開始します <br/> include($this->path . $file); / ファイルをインクルードします <br/> $contents = ob_get_contents(); // バッファの内容を取得します <br/> ob_end_clean(); // バッファリングを終了して破棄します <br/> return $contents; // 内容を返します <br/> } <br/>} <br/><br/>/** <br/>* <br/>* テンプレートのコンテンツの自動キャッシュを提供する Template の拡張機能。 <br/>*/ <br/>class CachedTemplate extends Template { <br/> var $cache_id;var $expire; <br/> var $cached; <br/><br/> /**<br/> * コンストラクター。 <br/> * <br/> * @param string $path テンプレート ファイルへのパス <br/> * @param string $cache_id 一意のキャッシュ識別子 <br/> * @param int $expire キャッシュが存続する秒数 <br/> * <br/> * @return void <br/>*/ <br/> function CachedTemplate($path, $cache_id = null, $expire = 900) { <br/> $this->Template($path); <br/> $this->cache_id = $cache_id ? 'キャッシュ/' 。 md5($キャッシュ_id): $キャッシュ_id; <br/> $this->expire = $expire; <br/> } <br/><br/> /**<br/> * 現在ロードされているcache_idに有効な <br/> * 対応するキャッシュ ファイルがあるかどうかをテストします。 <br/> * <br/> * @return bool <br/>*/ <br/> function is_cached() { <br/> if($this->cached) return true; <br/><br/> //cache_id を渡しましたか? <br/> if(!$this->cache_id) は false を返します。 <br><br> // キャッシュ ファイルは存在しますか? <br> if(!file_exists($this->cache_id)) は false を返します。 <br><br> // ファイルの時間を取得できますか? <br> if(!($mtime = filemtime($this->cache_id))) false を返します。 <br><br> // キャッシュの有効期限が切れましたか? <br> if(($mtime + $this->expire) < time()) { <br/> @unlink($this->cache_id); <br/> false を返します。 <br/> } <br/> else { <br/> /**<br/> * この is_cached() 呼び出しの結果をキャッシュします。 なぜ? したがって、 <br/> * 各テンプレートのオーバーヘッドを 2 倍にする必要はありません。 <br/> * キャッシュしなかった場合、ファイル システムにアクセスすることになります <br/> * 2 倍 (file_exists() と filemtime() [それぞれ 2 回])。 <br/>*/ <br/> $this->cached = true; <br/> true を返します。 <br/> } <br/> } <br/><br/> /**<br/> * この関数は、テンプレートのキャッシュされたコピー (存在する場合) を返します。 <br/> * それ以外の場合は、通常どおり解析してコンテンツをキャッシュします。 <br/> * <br/> * @param $file string テンプレート ファイル <br/> * <br/> * @return string <br/>*/ <br/> function fetch_cache($file) { <br/> if($this->is_cached()) { <br/> $fp = @fopen($this->cache_id, ' r'); <br/> $contents = fread($fp, filesize($this->cache_id)); <br/> fclose($fp); <br/> $contents を返します。 <br/> } <br/> else { <br/> $contents = $this->fetch($file); <br/><br/> // キャッシュを書き込みます <br/> if($fp = @fopen($this->cache_id, 'w')) { <br/> fwrite($fp, $contents); <br/> fclose($fp); <br/> } <br/> else { <br/> die('キャッシュを書き込めません。'); <br/> } <br/><br/> $contents を返します。 <br/> } <br/> } <br/>} <br/>?><br> さらに、ここで示されている重要な問題は、私が渡しているモジュールのファイル名の fetch() 関数です。 () のすべての変更。これは非常に有益であることに注意してください。モールド ハンドルの重要な点は、HTML コードから転送される PHP コードを分離するのではなく、転送される PHP コードを転送されるテーブルから分離することです。 <br><br>本文添付ファイル下ダウンロード:template.zip [1] http://www.massassi.com/bTemplate/<br>[2] http://smarty.php.net/<br>[3] http://www.sitepoint. com/examples/tempeng/template.zip<br>[4] http://opensource.org/licenses/mit-license.html<br>[5] http://www.opensource.org/<br>[6] http:// zend.com/store/products/zend-performance-suite.php<br>[7] http://www.php-accelerator.co.uk/<br>[8] http://www.php.net/manual/en /control-structs.alternative-syntax.php<br>[9] http://wact.sourceforge.net/index.php/TemplateView<br>[10] http://www.phppatterns.com/index.php/article/articleview /11/<br>[11] http://simplet.sourceforge.net/<br>[12] http://phppatterns.com/index.php/article/articleview/4/1/1/<br>[13] http:/ /smarty.php.net/<br><br>本文英文原版地址:http://www.sitepoint.com/article/1218/ <br> <br> <center> </center> <p style="width:100%;text-align:center;margin:10px 0"> <br> <br></p> <p style="width:100%;text-align:center;margin:10px 0"></p> </tr></div><div class="nphpQianMsg"><div class="clear"></div></div><div class="nphpQianSheng"><span>声明:</span><div>この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。</div></div></div><div class="nphpSytBox"><span>前の記事:<a class="dBlack" title="PEAR のエラー処理を詳しく見る" href="https://m.php.cn/ja/faq/241472.html">PEAR のエラー処理を詳しく見る</a></span><span>次の記事:<a class="dBlack" title="PEAR のエラー処理を詳しく見る" href="https://m.php.cn/ja/faq/241479.html">PEAR のエラー処理を詳しく見る</a></span></div><div class="nphpSytBox2"><div class="nphpZbktTitle"><h2>関連記事</h2><em><a href="https://m.php.cn/ja/article.html" class="bBlack"><i>続きを見る</i><b></b></a></em><div class="clear"></div></div><ins class="adsbygoogle" style="display:block" data-ad-format="fluid" data-ad-layout-key="-6t+ed+2i-1n-4w" data-ad-client="ca-pub-5902227090019525" data-ad-slot="8966999616"></ins><script> (adsbygoogle = window.adsbygoogle || []).push({}); </script><ul class="nphpXgwzList"><li><b></b><a href="https://m.php.cn/ja/faq/92233.html" title="Windows7系统下Netbeans+PHPUnit搭建PHP单元测试开发环境及PHPUn" class="aBlack">Windows7系统下Netbeans+PHPUnit搭建PHP单元测试开发环境及PHPUn</a><div class="clear"></div></li><li><b></b><a href="https://m.php.cn/ja/faq/97151.html" title="程序猿ProMonkey V2.03" class="aBlack">程序猿ProMonkey V2.03</a><div class="clear"></div></li><li><b></b><a href="https://m.php.cn/ja/faq/94770.html" title="PHP Navigator" class="aBlack">PHP Navigator</a><div class="clear"></div></li><li><b></b><a href="https://m.php.cn/ja/faq/90182.html" title="php返回数组中指定的一列(php5.5.0默认函数array_column()在php" class="aBlack">php返回数组中指定的一列(php5.5.0默认函数array_column()在php</a><div class="clear"></div></li><li><b></b><a href="https://m.php.cn/ja/faq/208396.html" title="htmlentitiesとhtmlspecialcharsの違いの詳しい説明" class="aBlack">htmlentitiesとhtmlspecialcharsの違いの詳しい説明</a><div class="clear"></div></li></ul></div></div><ins class="adsbygoogle" style="display:block" data-ad-format="autorelaxed" data-ad-client="ca-pub-5902227090019525" data-ad-slot="5027754603"></ins><script> (adsbygoogle = window.adsbygoogle || []).push({}); </script><footer><div class="footer"><div class="footertop"><img src="/static/imghwm/logo.png" alt=""><p>福祉オンライン PHP トレーニング,PHP 学習者の迅速な成長を支援します!</p></div><div class="footermid"><a href="https://m.php.cn/ja/about/us.html">私たちについて</a><a href="https://m.php.cn/ja/about/disclaimer.html">免責事項</a><a href="https://m.php.cn/ja/update/article_0_1.html">Sitemap</a></div><div class="footerbottom"><p> © php.cn All rights reserved </p></div></div></footer><script>isLogin = 0;</script><script type="text/javascript" src="/static/layui/layui.js"></script><script type="text/javascript" src="/static/js/global.js?4.9.47"></script></div><script src="https://vdse.bdstatic.com//search-video.v1.min.js"></script><link rel='stylesheet' id='_main-css' href='/static/css/viewer.min.css' type='text/css' media='all'/><script type='text/javascript' src='/static/js/viewer.min.js?1'></script><script type='text/javascript' src='/static/js/jquery-viewer.min.js'></script><script>jQuery.fn.wait = function (func, times, interval) { var _times = times || -1, //100次 _interval = interval || 20, //20毫秒每次 _self = this, _selector = this.selector, //选择器 _iIntervalID; //定时器id if( this.length ){ //如果已经获取到了,就直接执行函数 func && func.call(this); } else { _iIntervalID = setInterval(function() { if(!_times) { //是0就退出 clearInterval(_iIntervalID); } _times <= 0 || _times--; //如果是正数就 -- _self = $(_selector); //再次选择 if( _self.length ) { //判断是否取到 func && func.call(_self); clearInterval(_iIntervalID); } }, _interval); } return this; } $("table.syntaxhighlighter").wait(function() { $('table.syntaxhighlighter').append("<p class='cnblogs_code_footer'><span class='cnblogs_code_footer_icon'></span></p>"); }); $(document).on("click", ".cnblogs_code_footer",function(){ $(this).parents('table.syntaxhighlighter').css('display','inline-table');$(this).hide(); }); $('.nphpQianCont').viewer({navbar:true,title:false,toolbar:false,movable:false,viewed:function(){$('img').click(function(){$('.viewer-close').trigger('click');});}}); </script></body><!-- Matomo --><script> var _paq = window._paq = window._paq || []; /* tracker methods like "setCustomDimension" should be called before "trackPageView" */ _paq.push(['trackPageView']); _paq.push(['enableLinkTracking']); (function() { var u="https://tongji.php.cn/"; _paq.push(['setTrackerUrl', u+'matomo.php']); _paq.push(['setSiteId', '9']); var d=document, g=d.createElement('script'), s=d.getElementsByTagName('script')[0]; g.async=true; g.src=u+'matomo.js'; s.parentNode.insertBefore(g,s); })(); </script><!-- End Matomo Code --></html>