ホームページ > バックエンド開発 > PHPチュートリアル > PHP のカスタム テンプレート エンジンのサンプル コード共有

PHP のカスタム テンプレート エンジンのサンプル コード共有

黄舟
リリース: 2023-03-07 06:18:02
オリジナル
1649 人が閲覧しました

この記事では、PHPテンプレートエンジンについて詳しく紹介します。非常に良い基準値を持っています。エディターと一緒に見てみましょう

前にも言いました

ほとんどのプロジェクトチームでは、Webプログラムの開発はこのようなプロセスを経ます。企画書が提出された後、フロントエンドエンジニアが登場します。ウェブサイトモデルをバックエンドエンジニアに引き渡し、バックエンドエンジニアはバックエンドコードを使用してプログラムロジックを実装し、外観モデルを使用して基本的なアーキテクチャを作成し、プロジェクトが返されます。フロントエンドエンジニアが継続的に改善できるようサポートします。このように、プロジェクトではバックエンドエンジニアとフロントエンドエンジニアの間を何度も行き来することがあります。バックエンド エンジニアは関連する HTML タグに干渉しないため、フロントエンド コードとバックエンド コードを混在させる必要はありません。フロントエンド エンジニアは、設定ファイル、ダイナミック ブロック、その他のインターフェイス パーツのみが必要で、複雑なバックエンド コードに触れる必要はありません。したがって、現時点では適切なテンプレートをサポートすることが重要です。この記事では、PHPのテンプレートエンジンについて詳しく紹介します

概要

Webサイトテンプレートとは何ですか?正確には、Web サイトのページ テンプレートを指します。つまり、各ページは、構造、スタイル、ページ レイアウトを含む単なるテンプレートであり、Web コンテンツを作成するためのテンプレートであり、既存の Web ページと理解することもできます。 フレームワーク。ページスタイルの一貫性を保つために、テンプレート内の元のコンテンツをサーバー側データベースの動的コンテンツに置き換えることができます

PHP はサーバー側で実行される HTML 埋め込みスクリプト言語であるため、ほとんどの PHP は Web アプリケーション用に開発されています。初期の開発テンプレートは混合層データ プログラミングです。 MVC デザイン パターンでは、プログラム アプリケーション ロジックと Web ページ レンダリング ロジックを強制的に分離できますが、分離されるのはアプリケーションの入力、処理、出力だけです。Web ページ レンダリング ロジック (ビュー) も HTML コードおよび PHP プログラムと強く結合されます。 。 PHP スクリプトの作成者は、Web デザイナーと PHP 開発者の両方である必要があります

Web サイトのページ デザインを PHP アプリケーションからほぼ完全に分離できるソリューションは数多くあります。これらのソリューションは「テンプレート エンジン」と呼ばれ、階層分離の欠如によって引き起こされる問題を徐々に解消しています。テンプレートエンジンの目的は、上記の論理分離機能を実現することである。これにより、プログラム開発者はデータ制御や機能の実現に集中できます。したがって、テンプレート エンジンは会社の Web 開発チームによる使用に非常に適しており、誰もが専門知識を開発できるようになります

テンプレート エンジン テクノロジーの中核は比較的シンプルです。フロントエンドページをテンプレートファイルとして指定し、データベース出力やユーザーインタラクションなどの動的コンテンツを、特別な「区切り文字」を使用して含まれる「変数」としてこのテンプレートファイルに定義して配置するだけです。テンプレート ファイル内の対応する位置。ユーザーが参照すると、PHP スクリプト プログラムによってテンプレート ファイルが開かれ、テンプレート ファイル内で定義されている変数が置き換えられます。このようにして、テンプレート内の特殊変数が別の動的コンテンツに置き換えられると、必要なページが出力されます。現在、Smarty、PHPLIB、IPB など、PHP に適用できる成熟したテンプレートが多数あります。 。 PHP で書かれたこれらのテンプレート エンジンを使用すると、コードのコンテキストがより明確になり、構造がより合理的になります。また、Web サイトのメンテナンスと更新が容易になり、より良い開発環境が作成され、開発と設計作業の結合が容易になります。ただし、最も適切または完璧な PHP テンプレートはありません。なぜなら、PHPテンプレートは普及したものであり、特定の人向けに開発されたものではないからです。テンプレートの特性と用途を明確に理解した上で、テンプレートの長所と短所を十分に理解できれば、テンプレート エンジンを使用するか、どのテンプレート エンジンを使用するかを判断できます

カスタム テンプレート エンジン クラス

定義テンプレート エンジンは、テンプレート エンジンの動作メカニズムをよりよく把握し、Smarty を学習する準備を整えることができます。さらに重要なのは、独自の PHP テンプレート エンジンが固定されることはなく、プロジェクトのニーズに応じてカスタマイズできることです。次の例では、前に紹介したテンプレート エンジンの概念を通じて独自の単純なテンプレート エンジンが作成され、それを使用できます。テンプレートの基本的な機能を処理します。例: 以下に示すように、変数置換、

分岐構造

配列

ループトラバーサル、相互にネストされたテンプレートなど:

<?php
 /**
  file: mytpl.class.php 类名为MyTpl是自定义的模板引擎
  通过该类对象加载模板文件并解析,将解析后的结果输出 
 */
 class Mytpl {
  public $template_dir = &#39;templates&#39;;  //定义模板文件存放的目录 
  public $compile_dir = &#39;templates_c&#39;;  //定义通过模板引擎组合后文件存放目录
  public $left_delimiter = &#39;<{&#39;;   //在模板中嵌入动态数据变量的左定界符号
  public $right_delimiter = &#39;}>&#39;;   //在模板中嵌入动态数据变量的右定界符号
  private $tpl_vars = array();    //内部使用的临时变量
  /** 
   将PHP中分配的值会保存到成员属性$tpl_vars中,用于将模板中对应的变量进行替换 
   @param string $tpl_var 需要一个字符串参数作为关联数组下标,要和模板中的变量名对应 
   @param mixed $value  需要一个标量类型的值,用来分配给模板中变量的值  
  */
  function assign($tpl_var, $value = null) { 
   if ($tpl_var != &#39;&#39;)     
    $this->tpl_vars[$tpl_var] = $value;
  }
  /** 
   加载指定目录下的模板文件,并将替换后的内容生成组合文件存放到另一个指定目录下
   @param string $fileName 提供模板文件的文件名            
  */
   function display($fileName) { 
   /* 到指定的目录中寻找模板文件 */
   $tplFile = $this->template_dir.&#39;/&#39;.$fileName; 
   /* 如果需要处理的模板文件不存在,则退出并报告错误 */
   if(!file_exists($tplFile)) {     
    die("模板文件{$tplFile}不存在!");
   }
   /* 获取组合的模板文件,该文件中的内容都是被替换过的 */
   $comFileName = $this->compile_dir."/com_".$fileName.&#39;.php&#39;; 
   /* 判断替换后的文件是否存在或是存在但有改动,都需要重新创建 */
   if(!file_exists($comFileName) || filemtime($comFileName) < filemtime($tplFile)) {
    /* 调用内部替换模板方法 */
    $repContent = $this->tpl_replace(file_get_contents($tplFile)); 
    /* 保存由系统组合后的脚本文件 */
    file_put_contents($comFileName, $repContent);
   }
   /* 包含处理后的模板文件输出给客户端 */
   include($comFileName);     
  }
  /** 
   内部使用的私有方法,使用正则表达式将模板文件&#39;<{ }>&#39;中的语句替换为对应的值或PHP代码 
   @param string $content 提供从模板文件中读入的全部内容字符串 
   @return $repContent   返回替换后的字符串
  */
  private function tpl_replace($content) {
   /* 将左右定界符号中,有影响正则的特殊符号转义 例如,<{ }>转义\<\{ \}\> */
   $left = preg_quote($this->left_delimiter, &#39;/&#39;);
   $right = preg_quote($this->right_delimiter, &#39;/&#39;);
   /* 匹配模板中各种标识符的正则表达式的模式数组 */
   $pattern = array(  
    /* 匹配模板中变量 ,例如,"<{ $var }>" */
    &#39;/&#39;.$left.&#39;\s*\$([a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)\s*&#39;.$right.&#39;/i&#39;,  
    /* 匹配模板中if标识符,例如 "<{ if $col == "sex" }> <{ /if }>" */
    &#39;/&#39;.$left.&#39;\s*if\s*(.+?)\s*&#39;.$right.&#39;(.+?)&#39;.$left.&#39;\s*\/if\s*&#39;.$right.&#39;/ies&#39;,
    /* 匹配elseif标识符, 例如 "<{ elseif $col == "sex" }>" */
    &#39;/&#39;.$left.&#39;\s*else\s*if\s*(.+?)\s*&#39;.$right.&#39;/ies&#39;, 
    /* 匹配else标识符, 例如 "<{ else }>" */
    &#39;/&#39;.$left.&#39;\s*else\s*&#39;.$right.&#39;/is&#39;, 
    /* 用来匹配模板中的loop标识符,用来遍历数组中的值, 例如 "<{ loop $arrs $value }> <{ /loop}>" */
    &#39;/&#39;.$left.&#39;\s*loop\s+\$(\S+)\s+\$([a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)\s*&#39;.$right.&#39;(.+?)&#39;.$left.&#39;\s*\/loop\s*&#39;.$right.&#39;/is&#39;,
    /* 用来遍历数组中的键和值,例如 "<{ loop $arrs $key => $value }> <{ /loop}>" */
    &#39;/&#39;.$left.&#39;\s*loop\s+\$(\S+)\s+\$([a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)\s*=>\s*\$(\S+)\s*&#39;.$right.&#39;(.+?)&#39;.$left.&#39;\s*\/loop \s*&#39;.$right.&#39;/is&#39;, 
    /* 匹配include标识符, 例如,&#39;<{ include "header.html" }>&#39; */
    &#39;/&#39;.$left.&#39;\s*include\s+[\"\&#39;]?(.+?)[\"\&#39;]?\s*&#39;.$right.&#39;/ie&#39;     
   );
   /* 替换从模板中使用正则表达式匹配到的字符串数组 */
   $replacement = array( 
    /* 替换模板中的变量 <?php echo $this->tpl_vars["var"]; */
    &#39;<?php echo $this->tpl_vars["${1}"]; ?>&#39;,  
    /* 替换模板中的if字符串 <?php if($col == "sex") { ?> <?php } ?> */
    &#39;$this->stripvtags(\&#39;<?php if(${1}) { ?>\&#39;,\&#39;${2}<?php } ?>\&#39;)&#39;,  
    /* 替换elseif的字符串 <?php } elseif($col == "sex") { ?> */
    &#39;$this->stripvtags(\&#39;<?php } elseif(${1}) { ?>\&#39;,"")&#39;, 
    /* 替换else的字符串 <?php } else { ?> */
    &#39;<?php } else { ?>&#39;, 
    /* 以下两条用来替换模板中的loop标识符为foreach格式 */
    &#39;<?php foreach($this->tpl_vars["${1}"] as $this->tpl_vars["${2}"]) { ?>${3}<?php } ?>&#39;, 
    &#39;<?php foreach($this->tpl_vars["${1}"] as $this->tpl_vars["${2}"] => $this->tpl_vars["${3}"]) { ?>${4}<?php } ?>&#39;, 
    /*替换include的字符串*/
    &#39;file_get_contents($this->template_dir."/${1}")&#39;    
   );
   /* 使用正则替换函数处理 */
   $repContent = preg_replace($pattern, $replacement, $content);  
   /* 如果还有要替换的标识,递归调用自己再次替换 */
   if(preg_match(&#39;/&#39;.$left.&#39;([^(&#39;.$right.&#39;)]{1,})&#39;.$right.&#39;/&#39;, $repContent)) {  
    $repContent = $this->tpl_replace($repContent);    
   } 
   /* 返回替换后的字符串 */
   return $repContent;          
  }
   /**
   内部使用的私有方法,用来将条件语句中使用的变量替换为对应的值
   @param string $expr  提供模板中条件语句的开始标记   
   @param string $statement 提供模板中条件语句的结束标记 
   @return strin    将处理后的条件语句相连后返回 
  */
  private function stripvtags($expr, $statement=&#39;&#39;) {
   /* 匹配变量的正则 */
   $var_pattern = &#39;/\s*\$([a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)\s*/is&#39;; 
   /* 将变量替换为值 */
   $expr = preg_replace($var_pattern, &#39;$this->tpl_vars["${1}"]&#39;, $expr); 
   /* 将开始标记中的引号转义替换 */
   $expr = str_replace("\\\"", "\"", $expr);
   /* 替换语句体和结束标记中的引号 */
   $statement = str_replace("\\\"", "\"", $statement); 
   /* 将处理后的条件语句相连后返回 */
   return $expr.$statement;        
  }
 }
?>

在Mytpl类中声明的多个方法中,除被封装过的方法之外,只有两个公有方法assign()和display()在创建对象以后可以被凋用。其中assign()方法用来将PHP脚本中的数据分配给模板中对应的变量,display()方法则用来将特定的templates目录下的模板文件加载到PHP脚本中。同时将模板文件中使用“<{”和“>>”标记声明的自定义模板语句,匹配出来并替换成相对应的PHP语法格式,然后将替换后的内容保存在特定的templates_c目录下。在运行时还要编译成一个非模板技术的PHP文件,并将其以模板文件名加上“com_”前缀和“.php”的扩展名形式保存。再通过include()函数将处理后的模板文件包含,并使用PHP解析后发送给客户端

使用模板引擎

使用自定义的模板引擎比较容易,都是自己定义的语法格式。但要记住,所有流行的模板引繁解决方案都遵循同样的一组相同的核心实现原则,就是与编程语言一样,学习了一种语言就可以更容易地掌握其他语言。使用模板引擎最主要的原因就是将前端工程师和后端工程师的工作分开,所以模板引擎不仅后端工程师需要使用,前端工程师也需要使用

1、后端工程师对模板引擎的使用

在PHP脚本中包含模板引擎类所在的文件。如下所示:

require("mytpl.class.php");    //包含模板引擎类,相当于模板引擎安装
ログイン後にコピー

创建模板引擎类的对象并对一些成员属性进行初始化赋值。如下所示:

$tpl=new MyTpl(); //创建模板引擎类的对象,也可以根据参数对成员初始化

将动态数据(包括标量和数组类型的数据,例如从数据库的表中获得的数据数组)使用模板引擎对象中的assign()方法分配给模板文件,这个方法可以使用多次,将任意多个变量分配给模板。如下所示:

$tpl->assign("var","this is a value"); //可以分配标量类型数据,可以使用多次
$tpl->assign("arr",array(array(1,2),array("a","b"))); //也可以分配数组包括多维数组
ログイン後にコピー

在PHP脚本中通过调用模板对象中的display()方法,并将模板文件名作为参数传入,就会加载指定目录中对应的模板文件到PHP脚本中。再通过模板引擎中的替换方法对模板中自定义的语法进行解析,然后输出处理后的模板。如下所示:

$tpl->display("test.tpl");    //参数“test.tpl”为特定目录下的模板文件
ログイン後にコピー

2、前端工程师对模板引擎的使用

前端工程师需要将编写的模板文件存放到指定的目录中,这个目录是通过在模板对象中使用$template_dir属性指定的,默认的设置是当前目录下的“templates”目录。另外,模板文件的命名以及后缀名的设置可以随意,例如index.tpl、test.htm、header.tp;等

模板文件是通过使用HTML、CSS以及javascript等Web前台语言以编写的纯静态负而。但可以在模板文件中使用“<{”和“}>”两个分隔符中间定义一个变量(类似PHP中的变量格式),该变量可以接受并输出由PHP脚本中分配过来的动态数据。在模板中使用的“<{”和“}>”两个分隔符对,也可以根据个人爱好在模板引擎类中修改。如下所示:

姓名:<{$name}>,年龄:<{$age}>,性别:<{$sex}> //模板中使用占位符

如果在PHP脚本中是将数组分配给模板,也可以在模板中进行遍历,还可以通过嵌套的方式遍历多维数组。使用的是在模板引擎中定义的“<{loop}>”标记对,使用的方式和PHP中foreach结构的语法格式相似。如下所示:

<{loop $arr $value }>     //遍历数组$arr中的元素值
 数组中的元素值<{$value}>   //每次遍历输出元素中的值
<{/loop}>        //在模板中遍历数组的结束标记
<{loop $arr $key=>$value }>   //遍历数组$arr中的元素下标和元素值
 数组中的元素键<{$key}>    //每次遍历输出元素中的下标
 数组中的元素值<{$value}>   //每次遍历输出元素中的值
<{/loop}>        //在模板中遍历数组的结束标记
<{loop $arr $value }>     //遍历数组$arr中的元素值
 <{loop $arr $data }>    //使用嵌套标记遍历二维数组
  数组中的元素值<{$value}>  //每次遍历输出元素中的值
 <{/loop}>       //在模板中遍历数组的内层结束标记
<{/loop}>        //在模板中遍历数组的外层结束标记
ログイン後にコピー

模板引擎还可以解析在模板文件中使用特殊标记编写的分支结构,语法风格也是和PHP的分支结构类似。是通过在模板文件中使用“<{if}>”标记对实现选择结构,也可以实现多路分支和嵌套分支的选择结构。如下所示: 

<{if($var=="red")}>
 <p style="color:red">这是“红色”的字</p>
<{elseif($var=="green")}> 
 <p style="color:green">这是“绿色”的字</p>
<{else}>
 <{if($size=20)}>
  <p style="font-size:20">这是“20px”大小的字</p>
 <{/if}>
<{/if}>
ログイン後にコピー

在自定义的模板引擎中,也添加了在模板文件中包含其他模板文件的功能。可以使用“<{include‘子模板文件名'}>”标记将子模板包含到当前模板中,还支持在子模板中再次包括另外的子模板。如下所示:

<{include &#39;other.tpl&#39; }>
ログイン後にコピー

使用示例分析

通过在程序中加载模板引擎可以将前端语言与后端语言的代码分开。首先在PHP程序中获取数据库中存储的数据,再通过加载模板引擎将数据分配出去,然后将模板文件再通过模板引擎加载并处理后输出。所以PHP程序只是创建动态数据,加载模板引擎并将动态数据分配给模板,完成了PHP程序的工作。而模板的设汁也只需要前端工程师独立完成,使用HTML、CSS及javascript等前台页面设计语言编写。另外,在模板文件中还需要使用模板引擎可以解析的标记,将PHP中分配过来的动态数据在模板中引用

1、数据库的设计

假设数据库服务器在“localhost”主机上,连接的用户名和密码分别为“admin”和“123456”,在该服务器上创建一个名为“mydb”的数据库,并在该数据库中创建一个名为“User”的用户表。创建该表的SQL査询语句如下所示:

CREATE TABLE User(
 id SMALLINT(3) NOT NULL AUTO_INCREMENT,
 name VARCHAR(10) NOT NULL DEFAULT &#39;&#39;,
 sex VARCHAR(4) NOT NULL DEFAULT &#39;&#39;,
 age SMALLINT(2) NOT NULL DEFAULT &#39;0&#39;,
 email VARCHAR(20) NOT NULL DEFAULT &#39;&#39;,
 PRIMARY KEY (id)
);
ログイン後にコピー

用户表User创建完成以后,接着可以向该表中插入一些数据作为示例演示使用,SQL查询语句如下所示:

INSERT INTO User (name,sex,age,email) VALUES 
("a","男",27,"a@a.com"),
("b","女",22,"b@b.com"),
("c","女",30,"c@c.com"),
("d","女",24,d@d.com);
ログイン後にコピー

2、模板的设计

模板的设计不要出现任何的PHP代码,可以由前端人员来完成。在自定义的模板引擎中,规定了要到指定的目录中去寻找模板文件,这个特定的目录可以在创建模板引擎对象时指定,也可以使用默认的目录设置,默认可以将模板文件存放在当前目录中的“templates”目录下。本例共需要三个模板文件main.tpl、header.tpl和footer.tpl,都存放在这个默认的目录设置中。这三个模板文件的代码如下所示:

模板的头部文件header.tpl

<!DOCTYPE html>
<html lang="en">
<head>
 <meta charset="UTF-8">
 <title> <{$title}> </title>
</head>
<body>
ログイン後にコピー

模板的尾部文件footer.tpl

  <p style="width:200px;margin: 0 auto;">##### <{$author}> #####</p>  
 </body>
</html>
ログイン後にコピー

主模板文件main.tpl

<{include &#39;header.tpl&#39;}>
 <table border="1" align="center" width="500">
  <{ loop $users $user }>
   <tr> 
    <{loop $user $u }>

      <{if $u == "男" }>
       <td style="color:green">
      <{elseif $u == "女"}>
       <td style="color:red">
      <{else}>
       <td>
      <{/if}>

       <{$u}></td>    
    <{/loop}>
   </tr>
  <{/loop}>
 </table>
<{include &#39;footer.tpl&#39;}>
ログイン後にコピー

文件main.tpl是主模板文件,在该文件中使用<{include"header.tpl"}>和<{include"footer.tpl"}>两个标记分别在该文件的顶部和底部,将独立的头部和尾部模板文件包含到这个主模板文件中。并在该文件中使用<{tableName}>标记获取从PHP中动态分配过来的表名,以及使用双层<{loop}>标记嵌套,遍历从PHP中动态分配过来的在数据库中获取到的二维数组$Users,还在<{loop}>标记中使用条件选择标记<{if}>组合,将数据中性别为“男”的表格背景设置为红色和一些其他判断。被包含进来的头部模板文件header.tpl和尾部模板文件footer.tpl也同样可以获取从PHP中动态分配给模板的数据

3、PHP程序设计

通过模板引擎的使用,PHP程序员在编写代码时,只需要PHP一种语言就可以了,不用再去使用HTML、CSS以及javascript等页面设计语言完成前端的工作了。下面是一个文件名为index.php的PHP脚本文件,和模板引擎类所在的文件mytpl_class.php在同一个目录下。代码如下所示:

<?php
 //包含模板引擎类
 include "mytpl.class.php";
 //创建模板引擎对象
 $tpl = new Mytpl;
 //连接数据库
 $pdo = new PDO("mysql:host=localhost;dbname=mydb", "admin", "123456");
 //执行SQL语句
 $stmt = $pdo -> prepare("select id, name, sex,age,email from User order by id");
 $stmt ->execute();
 $data = $stmt -> fetchAll(PDO::FETCH_ASSOC);
 //这是从数据库获取的动态数据,需要在模板中显示
 $tpl->assign(&#39;title&#39;,"自定义模板引擎");$tpl->assign(&#39;auto&#39;,"小火柴");
 $tpl->assign(&#39;users&#39;,$data);
 $tpl -> display("main.tpl");
?>
ログイン後にコピー

在上面的PHP脚本文件中,通过PDO对象连接MySQL服务器,并获取用户表User中的全部记录,并以PHP的二维数组变量形式保存在变量data中。接着使用包含进来的当前目录下的“mytplclss.php”文件,创建并初始化模板引擎类的对象data中。接着使用包含进来的当前目录下的“mytplclss.php”文件,创建并初始化模板引擎类的对象tpl。再通过该对象中的assign()方法向模板分配一些数据,然后使用该对象中的display()方法载入模板文件main.tpl。并将模板中标记的特殊变量替换为从PHP中分配的动态数据,处理完毕以后输出模板页面。页面的输出结果如下所示

限于各种不同的条件限制,比如时间、经验,做一个自定义的PHP模板引擎是非常困难的。其实,需要的并不是重新构造一个PHP模板,而是选择一个最贴近自己的PHP模板加以改造

以上がPHP のカスタム テンプレート エンジンのサンプル コード共有の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

関連ラベル:
php
ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
最新の問題
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート