Maison  >  Article  >  développement back-end  >  Exemple de partage de code pour le moteur de modèles personnalisés de PHP

Exemple de partage de code pour le moteur de modèles personnalisés de PHP

黄舟
黄舟original
2017-03-27 09:37:031628parcourir

Cet article présentera le moteur de modèles en PHP en détail. A une très bonne valeur de référence. Jetons-y un coup d'œil avec l'éditeur ci-dessous

Les mots précédents

Dans la plupart des équipes de projet, le développement d'un programme Web suivra le processus suivant : planifier la soumission du document Après cela, l'ingénieur front-end a fait l'apparence modèle du site Web, puis l'a remis à l'ingénieur back-end, qui a utilisé le code back-end pour implémenter la logique du programme, et a utilisé l'apparence modèle pour réaliser l'architecture de base . Le projet est ensuite renvoyé aux ingénieurs front-end pour un affinement ultérieur. De cette façon, le projet peut faire plusieurs allers-retours entre les ingénieurs back-end et les ingénieurs front-end. Étant donné que l'ingénieur back-end n'interfère avec aucune balise HTML associée, il n'est pas nécessaire de mélanger le code front-end et le code back-end. Les ingénieurs front-end n'ont besoin que de fichiers de configuration, de blocs dynamiques et d'autres éléments d'interface, et n'ont pas besoin de toucher au code back-end complexe. Par conséquent, il est important d’avoir un bon support de modèles à ce moment-là. Cet article présentera en détail le moteur de modèles en PHP

Présentation

Qu'est-ce qu'un modèle de site Web ? Pour être précis, il fait référence au modèle de page du site Web, c'est-à-dire que chaque page n'est qu'un modèle, comprenant la structure, le style et la mise en page. Il s'agit d'un modèle pour créer du contenu Web, et peut également être compris. en tant que page Web existanteFrame. Le contenu original du modèle peut être remplacé par du contenu dynamique de la base de données côté serveur afin de conserver la cohérence du style de page.

PHP est un langage de script intégré au HTML exécuté côté serveur, donc la plupart des applications sont destinées au Web. applications développées avec PHP, le modèle de développement initial est la programmation de données à couches mixtes. Bien que le modèle de conception MVC puisse séparer avec force la logique d'application du programme et la logique de rendu de page Web, il ne sépare que l'entrée, le traitement et la sortie de l'application. La logique de rendu de page Web (vue) sera également fortement couplée au code HTML et aux programmes PHP. . Le rédacteur de scripts PHP doit être à la fois un web designer et un développeur PHP

Il existe de nombreuses solutions qui permettent de séparer presque complètement la conception des pages du site Web et de l'application PHP. Ces solutions sont appelées « moteurs de modèles » et éliminent progressivement les difficultés causées par le manque de séparation hiérarchique. Le but du moteur de modèles est de réaliser la fonction de séparation logique mentionnée ci-dessus. Il permet aux développeurs de programmes de se concentrer sur le contrôle des données ou sur la réalisation des fonctions. Par conséquent, le moteur de modèles est très approprié pour être utilisé par l'équipe de développement Web de l'entreprise, permettant à chacun d'exercer son expertise

Le cœur de la technologie du moteur de modèles est relativement simple. Spécifiez simplement la page frontale en tant que fichier modèle et définissez le contenu dynamique de ce fichier modèle, tel que la sortie de la base de données, l'interaction de l'utilisateur, etc., en tant que "variables" contenues à l'aide de "délimiteurs" spéciaux. puis placez-le à l'emplacement correspondant dans le fichier modèle. Lorsque l'utilisateur navigue, le fichier modèle est ouvert par le programme de script PHP et les variables définies dans le fichier modèle sont remplacées. De cette façon, lorsque les variables spéciales du modèle sont remplacées par un contenu dynamique différent, la page requise sera affichée

Actuellement, il existe de nombreux modèles matures qui peuvent être appliqués en PHP, tels que Smarty, PHPLIB, IPB Des dizaines d'autres. L'utilisation de ces moteurs de modèles écrits en PHP peut rendre le contexte du code plus clair et la structure plus rationnelle. Cela peut également faciliter la maintenance et les mises à jour du site Web, créer un meilleur environnement de développement et faciliter la combinaison des travaux de développement et de conception. Cependant, aucun modèle PHP n’est le plus adapté ou le plus parfait. Parce que les modèles PHP sont des choses populaires et ne sont pas développés pour une certaine personne. Si vous pouvez pleinement comprendre les avantages et les inconvénients des modèles sur la base d'une compréhension claire de leurs caractéristiques et de leurs applications, vous pouvez savoir s'il faut choisir d'utiliser un moteur de modèles ou quel moteur de modèles utiliser

Personnaliser les modèles Classe de moteur

Personnalisez le moteur de modèle, qui peut mieux comprendre le mécanisme de fonctionnement du moteur de modèle et vous préparer à l'apprentissage de Smarty. Plus important encore, votre propre moteur de modèles PHP n'est jamais fixe et peut être personnalisé en fonction des besoins du projet

Dans l'exemple suivant, votre propre moteur de modèles PHP est créé grâce au concept de moteur de modèles introduit précédemment. moteur de modèles qui peut être utilisé pour gérer les fonctionnalités de base des modèles. Par exemple : substitution de variable, structure de branche, tableau boucle traversée et modèles imbriqués les uns dans les autres, etc., comme indiqué ci-dessous :

<?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脚本中。同时将模板文件中使用“fa5e847075b157e00c9630361edd1a59>”标记声明的自定义模板语句,匹配出来并替换成相对应的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前台语言以编写的纯静态负而。但可以在模板文件中使用“a2a890d1eab90800994daff8bb7fc69e”两个分隔符中间定义一个变量(类似PHP中的变量格式),该变量可以接受并输出由PHP脚本中分配过来的动态数据。在模板中使用的“a2a890d1eab90800994daff8bb7fc69e”两个分隔符对,也可以根据个人爱好在模板引擎类中修改。如下所示:

姓名:f1ae60a094afb5383c24c6d7d49bae7e,年龄:ffba6e22b13d0326f3e6211269694a5b,性别:1416cefc31bf4e1bc6126908c09b2ed4 //模板中使用占位符

如果在PHP脚本中是将数组分配给模板,也可以在模板中进行遍历,还可以通过嵌套的方式遍历多维数组。使用的是在模板引擎中定义的“180f3c6ca551a35ecefd4b3ba05bd4a5”标记对,使用的方式和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的分支结构类似。是通过在模板文件中使用“45281049cbb9d3b9169f7d17da261b60”标记对实现选择结构,也可以实现多路分支和嵌套分支的选择结构。如下所示: 

<{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}>

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

<{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是主模板文件,在该文件中使用6eaa5ab26c10a3f864f56118cb598a8f和74b967363d8f1808137a4944882c558f两个标记分别在该文件的顶部和底部,将独立的头部和尾部模板文件包含到这个主模板文件中。并在该文件中使用bdced278cc5ac51b4cd270e445a6a1a2标记获取从PHP中动态分配过来的表名,以及使用双层180f3c6ca551a35ecefd4b3ba05bd4a5标记嵌套,遍历从PHP中动态分配过来的在数据库中获取到的二维数组$Users,还在180f3c6ca551a35ecefd4b3ba05bd4a5标记中使用条件选择标记45281049cbb9d3b9169f7d17da261b60组合,将数据中性别为“男”的表格背景设置为红色和一些其他判断。被包含进来的头部模板文件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模板加以改造

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn