良い一日、
PHPのプロジェクト用のテンプレートエンジンについてお話しします。
私は自転車を発明したとして非難されるリスクがあることを理解しているので、私の動機を説明します:テンプレートエンジンのほとんどは、
Smarty 、
Quickyなどすべて、最初は私には向いていません。同じロジックの独自の構文。
言い換えれば、これ:
{ ? $x = 2 + 2 }
またはそのような
- { foreach name = my from = array ( 'One' 、 'Two' 、 'Three' ) key = "i" item = "text" }
私にとってのアプローチは絶対に受け入れられません!
おそらく、すべてのテンプレートエンジンの中で、xtemplateは私の要件を最も満たしていますが、たとえば、すべてのページをブロックで囲む必要があることや、コンパイルではなくテンプレートを解釈する必要があるなど、多くの欠点があります。できません。 そして最後に、機能の追加に問題がなく、また以前に使用したことのあるネイティブテンプレートエンジンと互換性があるように、テンプレートエンジンを作成することにしました。 事実は、その設計
- $ tpl- > assign_var = 'abc' ;
どのネイティブテンプレートエンジンがよく使用するか、私は次のようなものよりもはるかに好きです:
- $ thl- > assign ( 'assigned_var' 、 'abc' ) ;
ある時点で、自分に合ったテンプレートエンジンを探すよりも、独自のテンプレートエンジンを書く方が簡単だと気づきました。 そして、私は彼が正しかったと思う、なぜなら問題は数晩かかったからだ。
一般的に言えば、このプロセスは私にとってかなり興味深いように思われ、コミュニティと話し合いたい点がたくさんありました。
構文の説明から始めます。
1)変数:
「{$」を除くすべてが通常どおりです
ビジネスロジック | 模様 |
- $ tpl- > var_name = '...' ;
| - { var_name }
|
- $ tpl- > var_name [ 'sub_var' ] = '...' ;
| - { var_name。 sub_var }
|
2)ブロック:
{foreach name = my from = array( 'One'、 'Two'、 'Three')key = "i" item = "text"}のような構造を取り除くために必要です。
xtplのように、わずかに自動化されています。つまり、ブロックを解析する(複製するとも言います)ため、テンプレートにデータの配列を渡すだけで十分です。
ビジネスロジック | 模様 |
- $ tpl- > block_name [ ] [ 'num' ] = '4' ;
- $ tpl- > block_name [ ] [ 'num' ] = '8' ;
- $ tpl- > block_name [ ] [ 'num' ] = '15' ;
| - <!-begin:block_name->
- { block_name。 num }
- <!-終了:block_name->
|
- $ tpl- > words [ 'block' ] = array (
- O => array ( 'word' => 'A' ) 、
- 1 =>配列( 'word' => 'B' ) 、
- 2 => array ( 'word' => 'C' ) 、
- ) ;
| - <!-begin:words.block->
- {言葉。 ブロック 単語 }
- <!-終了:words.block->
|
内部にブロック変数を表示するには、{block_name.variable_name}という名前を付ける必要があります
これにより、内部からブロック変数と外部変数の両方にアクセスできます。
ブロックは、絶対に任意の変数にすることができます。たとえば、2番目の例では、「words」配列の「block」要素にブロックが構築されます
ブロックは別のブロック内に存在することもできます。たとえば、乗算表を作成する簡単な方法を次に示します。
ビジネスロジック | 模様 |
- for ( $ i = 1 ; $ i < 10 ; $ i ++ )
- for ( $ j = 1 ; $ j < 10 ; $ j ++ )
- $ tpl- > table [ $ i ] [ 'row' ] [ $ j ] [ 'num' ] = $ i * $ j ;
| - <表>
- <!-begin:table->
- <tr>
- <!-begin:table.row->
- <td> {テーブル。 行 。 num } </ td>
- <!-終了:table.row->
- </ tr>
- <!-終了:テーブル->
- </ table>
|
3)チェック:
本質的に、一種のブロック。 内部にあるものを表示するか、変数に基づいていないかを表示するために必要です。 例でより明確になります。
ビジネスロジック | 模様 |
- $ tpl- > f_text = true ;
| - <!-if:f_text->
- f_text == trueの場合、このテキストが表示されます
- <!-終了:f_text->
|
- $ tpl- > f_text = false ;
| - <!-if:f_text->
- 顧客には表示されないので、ここに何かを書くことができます
- <!-終了:f_text->
|
4)機能:
これはより実験的な機能です。このアプローチに生命権があるかどうかの意見を聞きたいと思います。
Tpl.class.phpファイル | 模様 |
- function up ( $ text ) {
- strtoupper ( $ text )を 返し ます
- }
| - { up }テキストを大きくする{ / up }
|
関数をテンプレートクラスに追加する必要があるという事実に注目します。
現時点では、関数は1つのパラメーターのみで機能します。パラメーターの数を次のように拡張する方法を考えます。
- { func ( param2、param3 ) } param1 { / func }
、または:
- { func } param1 | param2 | param3 { / func }
または何か他のもの。 最初のオプションに傾いている間は、実装が簡単です!
原則について:
テンプレートエンジンを2つの部分に分けることにしました。
1)テンプレートエンジン自体(可能な限りコンパクト、必要なものすべて)
2)コンパイラ(およびここでは他のすべて)
テンプレートが既にコンパイルされており、それ以降変更されていない場合、8 kbのコンパイラコードには意味がないため、これはパフォーマンスを改善するために必要です。
テンプレート内の包含プロセスにより、私は多くのことを考えました。
一見、些細なことに思えるかもしれませんが、そうではありません。 一般的に、包含物は静的と動的の2つの部分に分割する必要がありました。 静的包含は、たとえば次のような通常の包含です。
- <!-include:some_page.html->
このインクルードは次のように処理されます-some_page.htmlのコードがその場所に挿入され、コンパイルされたテンプレートのファイルの変更時間はテンプレート自体よりも1秒長くなります。これにより、テンプレートエンジンは、コンパイラによって作成された特別なファイルを接続する必要があることを学習します次の行が追加されます。
- if ( filemtime ( './some_page.html')!= 1237369507 ) $ needCompile = true ;
したがって、このファイルを変更すると、テンプレート全体が再コンパイルされます。
なぜこれが必要なのですか、なぜインクルードを挿入しないのですか? しかし、1000行のブロックを表示したい場合は、その中に便宜上インクルージョンが挿入されますか? 次に、このようなトリックはパフォーマンスに大いに役立ちます!
次に、別のタイプの包含について-動的です。 この奇跡は、私のテンプレートエンジンでは次のようになります。
- <!-include:{page_name} .html->
つまり、事前定義されたファイルは含めませんが、その名前または名前の一部を変数から取得します! 非常に便利な場合もありますが、変数のビジネスロジックに別のファイルを含める必要があるため、このアプローチの古い方法は機能しません。そのため、この設計は次のコードにコンパイルされます。
- <?php $ this- > render ( '' 。 $ this- > page_name 。 '.html' ) ; ?>
現時点では、そのような包含はブロック内では機能しません、つまり機能しますが、接続されたファイル内ではブロック変数は使用できませんが、xtplとは異なり、何らかの種類の循環出力にのみブロックが必要なので、これはそれほど怖くないと思います配列。
内部のPHPコード:
安全に使用でき、よく考えましたが、テンプレートのphpコードを禁止しないことにしました。
私はそれが多くの論争を引き起こすことを理解していますが、理にかなっているときにそのような状況に遭遇したことはなく、状況によっては不便を引き起こさないため、phpを禁止することは意味がないと思います。
そして最後に、構文がどのようなものになるかを決定する際に、私はどのような原則に導かれましたか:
1)最小限のロジック、すべてのロジック-ビジネスロジック
2)すべてが可能な限り自然
3)少ないコード
4)最大の可能性
テンプレートエンジン自体のコード:
- <?php
- クラス tpl {
- 関数 tpl ( $ tplDir 、 $ tmpDir ) {
- $ this- > tplDir = $ tplDir ;
- $ this- > tmpDir = $ tmpDir ;
- }
- function Render ( $ Path ) {
- $ tmpName = 'tpl_' 。 str_replace ( 配列 ( 「 /」、「\\」)、「.」、$ パス ) 。 '.php' ;
- $ tmpPath = $ this- > tmpDir 。 '/' $ tmpName ;
- if ( file_exists ( $ tmpPath ) )
- $ tmpChange = filemtime ( $ tmpPath ) ;
- $ tplChange = filemtime ( $パス ) ;
- if ( $ tplChange + 1 == $ tmpChange ) include ( $ tmpPath 。 '.coll.php' ) ;
- elseif ( $ tplChange != $ tmpChange ) $ needCompile = true ;
- if ( $ needCompile ) {
- #コンパイラーを呼び出す
- include_once 'tcompiler.class.php' ;
- $ compiler = new tcompiler ( $ this 、 $ this- > tmpDir ) ;
- $ compiler- > compile ( $ this- > tplDir 。 ' /'。$ Path 、 $ tmpPath ) ;
- }
- インクルード $ tmpPath ;
- }
- }
- ?>
ご覧のように、多くではなく高速です!
一見すると、そのような自動修正のように見えるかもしれません:
- $ tplName = 'tpl_' 。 str_replace ( array ( '/' 、 '\\' ) 、 '。' 、 $ path ) 。 '.php' ;
それは長い間機能し、ハッシュを使用する方が良いですが、私はそれをテストしました、ハッシュは長持ちします。
コード比較:
アプローチの読みやすさと使いやすさをすばやく比較できるように、同じことを行うさまざまなテンプレートエンジンのコードリストを便利にリストすることにしました。
私の- $ tpl- > num = 4815162342 ;
- $ tpl- > post [ 'page' ] [ 'id' ] = 316 ;
- for ( $ i = 1 ; $ i < 30 ; $ i ++ ) $ tpl- > bin [ ] = array ( 'dec' => $ i 、 'bin' => decbin ( $ i ) ) ;
- for ( $ i = 1 ; $ i < 10 ; $ i ++ ) for ( $ j = 1 ; $ j < 10 ; $ j ++ ) $ tpl- > table [ $ i ] [ 'row' ] [ $ j ] [ 'num' ] = $ i * $ j ;
スマーティー/クイック- $ smarty- > assign ( "num" 、 4815162342 ) ;
- $ smarty- > assign ( "post" 、 array ( 'page' => array ( 'id' => 316 ) ) ) ;
- for ( $ i = 1 ; $ i < 30 ; $ i ++ ) $ bin [ ] = array ( 'dec' => $ i 、 'bin' => decbin ( $ i ) ) ;
- $ smarty- > assign ( "bin" 、 $ bin ) ;
- for ( $ i = 1 ; $ i < 10 ; $ i ++ ) for ( $ j = 1 ; $ j < 10 ; $ j ++ ) $ table [ $ i ] [ 'row' ] [ $ j ] [ 'num' ] = $ i * $ j ;
- $ smarty- > assign ( "table" 、 $ table ) ;
Xtemplate- $ xtpl- > assign ( 'num' 、 4815162342 ) ;
- $ post [ 'page' ] [ 'id' ] = 316 ;
- $ xtpl- > assign ( 'post' 、 $ post ) ;
- for ( $ i = 1 ; $ i < 30 ; $ i ++ ) $ xtpl- > insert_loop ( "page.bin" 、 array ( "dec" => $ i 、 "bin" => decbin ( $ i ) ) ) ;
- for ( $ i = 1 ; $ i < 10 ; $ i ++ ) {
- for ( $ j = 1 ; $ j < 10 ; $ j ++ ) $ xtpl- > insert_loop ( "page.table.row" 、 'rownum' 、 $ i * $ j ) ;
- $ xtpl- > parse ( "page.table" ) ;
- }
接続:
テンプレートエンジンは次のように接続されます。
- require_once 'template_path_path / tpl.class.php' ;
- $ tpl = new tpl ( 'path_to_folder_with_patterns' 、 'path_to_folder_with_cache_folder' ) ;
キャッシュで適切なフォルダーを指定することを忘れないでください!
ダウンロード:
テンプレートエンジンは
ダウンロードするためにここにあり
ますが 、
ベータ版にすぎませんが、深刻なプロジェクトではテストしないでください。このトピックに関するコメントやアイデアを聞きたいだけです。
実験が成功し、ネイティブテンプレートエンジンと通常のテンプレートエンジンの同様のハイブリッドが必要な場合は、間違いなく開発します。 ちなみに、ほとんどの場合、「LL」と呼ばれます。
バグに関しては、oleg <dog> emby.ruの購読を解除してください
結論:
結論として、「このテンプレートエンジンはphpネイティブよりも高速である場合がある」などの重要なステートメントは作成しません。 少なくとも、テンプレートとそのコンパイル済みバージョンの変更日を比較する必要があるため、ベラルーシのトラクターが新品の
ポルシェパナメーラよりも速い場合があることを理解しています。少なくとも、FSへの2つの追加呼び出しであるためです。 最適化に関しては、ネイティブコードを最適化することを誰も気にしません。
もちろん、すべてのテンプレートエンジンと同様に、私のものはネイティブphpよりも動作が遅くなりますが、ほんの少し、証拠として、テスト結果を示します。
UFOが結果に影響を与えないことを確認するために、すべてのテストが数回実行されました。 それが
ここに投稿された場合。