`
xcgh
  • 浏览: 77597 次
  • 来自: ...
社区版块
存档分类
最新评论

一个方便易用的小模板处理类

阅读更多
一个方便易用的小模板处理类
在PHP中使用模板技术,一直是一个受欢迎的技术。自从2001年开始,PHP的很多爱好者,在PHP中引用了MVC开发模式后,模板技术就更为火热。

 

网上很多出名的模板引擎,如phplib的template、FastTemplate、easyTPL、BTemplate以及现在受php.net推宠的Smarty模板引擎。

我个人非常喜欢钟爱那些短小精悍的php代码,像Smarty这些动折2000多行的代码实现的模板引擎,一般不是我的钟爱。

前一段时间,看了phpe.net上有一篇文章叫<<超越模板引擎>>感觉那个老外所说确实极其有道理。他这样说:Smarty的目标是"把业务逻辑从表现中分离出来"而不是"PHP代码和HTML代码的分离"。但是Smarty确实也太庞大了,如果我在使用Smarty的话,我会感觉Smarty会不会影响php代码执行效率,首先在解析2000多行的Smarty代码就可能会带来很大延迟。

受<<超越模板引擎>>一文作者影响,我感觉到php本身就是一个嵌入式的脚本语言,如果我们能够使用用简单的php代码写成的模板,而在运行时直接将他include进来那不是更为快捷?比如像如下这个样子的代码:

My name is {myname}.
为什么我们不直接写成
My name is <?=$myname?>.
这样样子呢?

还有模板里常用的列表,其实也是简单的loop

<!-- BEGIN user_list -->
User ID      : {var0}
User Name : {var1}
<!-- END user_list -->

为什么我们不直接写成如下的代码

PHP:
<!---->foreach ( $user_list as $user ) { ?>
User ID : <!---->['id']?>
User Name : <!---->['name']?>
<!---->} ?>


其实早在一年前,我就尝试用这种方法去做一些企业和政府的WebOS,只是当时,还没有意识这样做带来的好处。只是感觉这样的模板我不需要单独的代码去处理他,只是简单的include一下就ok了。而且,我记得当时在做这些用php语言直接写出的模板的时候,非常快捷,以至于到后来,参与开发几个美工都因此对php的程序开发,发生了很大的兴趣,开始学习php的脚本语言。

最近又受<<超越模板引擎>>一文影响,所以决定根据他的思想去实现一个模板处理的类,经过了二三天的每天像榨水果汁一样挤出的几个小时去完成了一个模板类。现在张贴在此,以便能有志同道合朋友能够与我一起讨论。

考虑了现在带会经常使用{name}的这样的标记去做模板,所以我写一个简单的ParseHTM()的方法,去解析这样的文件,将其转换为<?=$name?>这样的php模板。然后将转换后的文件存贮到相应的cache目录中去,然后提供一个ParsePHP()方法去简单的include文件然后在主程序中echo输出。在实现的时候,我为了简化调用方法.使用了一个Parse()方法去呼叫上述两个私有方法.

以下是代码示例:

首先给出目录结构:
 \  根目录
├─cache           存放php模板缓存的文件
├─includes        类库存放目录
│  └─template    模板处理template.php类库文件存放目录
└─templates       模板目录
    ├─imgs           模板文件的图片目录
    │  └─ver.1
    └─tpls           模板文件目录
        └─ver.1

示例一:对于html类型的模板文件的处理.
test.htm.php 模板文件存放在 \templates\tpls\ver.1\目录下
<html>

<head>
    <title>{title}</title>
</head>

<body>
<!-- Trim php code that can't occur in HTML type template file. Now , that will be disable . -->
<?
print_r($_ENV);
?>
<?=$test?>
<? if ( $a == $b ) echo 'a==b'; ?>

<!--IF condition-->
<table border="1" align="center">
    <tr>
        <td>$condition is TRUE</td>
    </tr>
</table>
<!--ENDIF-->

<!--IF a == b-->
<table border="1" align="center">
    <tr>
        <td>$a == $b</td>
    </tr>
</table>
<!--ENDIF-->

<!--IF a != b-->
<table border="1" align="center">
    <tr>
        <td>$a != $b</td>
    </tr>
</table>
<!--ENDIF-->

<table border="1" align="center">
    <tr>
        <td>id</td>
        <td>name</td>
    </tr>

    <!--LIST user_list AS user-->
    <tr>
        <td>{user[id]}</td>
        <td>{user[name]}</td>
    </tr>
    <!--ENDLIST-->
</table>

</body>

</html>

test_htm.php文件对类库调用示例,本文件存放在 \ 目录下
下面是对这样的html类型的模板出理调用的具体过程.

PHP:
<!----> require_once('includes/template/template.php');

$tpl = new Template;
$tpl->SetFile('templates/tpls/ver.1/test.htm.php');

// 对于htm类型模板来说,通过此设置编译后的模板文件
$tpl->SetCacheDir('cache/');

$tpl->SetVar('title','I love jear');
$tpl->SetVar('condition',TRUE);
$tpl->SetVar('a','a');
$tpl->SetVar('b','a');

$user_list = array(
array(
'id' => '1',
'name' => 'Stangly.wrong'
),
array(
'id' => '2',
'name' => 'Jear'
),
);
$tpl->SetVar('user_list',$user_list);

echo $tpl->Parse(TPL_HTM, TRUE);

?>



观察一下目录结构的变化
\
├─cache
│  └─templates
│      └─tpls
│          └─ver.1
├─includes
│  └─template
└─templates
    ├─imgs
    │  └─ver.1
    └─tpls
        └─ver.1

程序会自动在cache目录下,建立与template文件存放的路径相同的目录路径去存放编译后的模板文件。这样个人感觉非常便于查找与排错。

示例二:对于php类型的模板文件的处理,观察一下与htm类型的模板文件有什么不同?是不是所有 {title} 这样的标记都被替换为 <?=$title?>这种形式,以及对于所谓的 block 也被直接替换为 foreach() 方式。

test.php.php 模板文件存放在 \templates\tpls\ver.1\目录下

<html>

<head>
    <title><?=$title?></title>
</head>

<body>

<? if ($condition) { ?>
<table border="1" align="center">
    <tr>
        <td>$condition is TRUE !</td>
    </tr>
</table>
<? } ?>

<? if ($a == $b) { ?>
<table border="1" align="center">
    <tr>
        <td>$a == $b</td>
    </tr>
</table>
<? } ?>

<? if ($a != $b) { ?>
<table border="1" align="center">
    <tr>
        <td>$a != $b</td>
    </tr>
</table>
<? } ?>

<table border="1" align="center">
    <tr>
        <td>id</td>
        <td>name</td>
    </tr>

    <? foreach ( $user_list as $user ) { ?>
    <tr>
        <td><?=$user[id]?></td>
        <td><?=$user[name]?></td>
    </tr>
    <? } ?>
</table>

</body>

</html>

test_htm.php文件对类库调用示例,本文件存放在 \ 目录下
下面是对这样的html类型的模板出理调用的具体过程.

PHP:
<!----> require_once('includes/template/template.php');

$tpl = new Template;
$tpl->SetFile('templates/tpls/ver.1/test.php.php');

// 对于 php 文件来说, 此设置无效
//$tpl->SetCacheDir('cache/');
//

$tpl->SetVar('title','I love jear');
$tpl->SetVar('condition',TRUE);
$tpl->SetVar('a','a');
$tpl->SetVar('b','a');

$users_list = array(
array(
'id' => '1',
'name' => 'Stangly.wrong'
),
array(
'id' => '2',
'name' => 'Jear'
),
);
$tpl->SetVar('user_list',$users_list);

echo $tpl->Parse(TPL_PHP);
?>


以上就是模板类的调用示例,以及模板文件内容的格式。

最后给出template.php文件,他存放于 /includes/template/ 目录下。

PHP:
<!----> // -------------------------------------------------------
// Filename : template.php
// Created : 2004-11-6 13:46
// Author : Stangly.Wrong
// Version : 1.0.0
// Description : Parse template
// Modified : 2004-11-7 15:10
// -------------------------------------------------------

// 定义模板类型
define( 'TPL_HTM', 'htm' );
define( 'TPL_PHP', 'php' );
// 定义默认的缓存目录
define( 'TPL_CACHE_DIR', './cache/');
// 编译后的 TPL_HTM 类型缓存文件名 前缀
define( 'TPL_COMPLIE_FILE_PREFIX','_c_');

Class Template
{
// 模板文件存放的目录
var $_root_dir = NULL;
// 模板文件名
var $_file = NULL;
// 模板文件类型
var $_file_type = TPL_PHP;
// 存贮模板内定义的变量
var $_var = array();

// 编译和缓存文件存放目录
var $_cache_dir = TPL_CACHE_DIR;

// Private function
//
// 参数:
// $f 为PHP类型模板完整路径文件名
//
// 解析php模板文件
//
// 返回解析的结果, 用于直接输出到客户端
//
function &_ParsePHP( $f )
{
if ( !file_exists( $f ) )
{
die('Open file '.$f.' failed !');
}
extract($this->_var);
ob_start();
include($f);
$contents = &ob_get_contents();
ob_end_clean();
return $contents;
}

// Private function
//
// 参数:
// $f 为HTM类型模板完整路径文件名
// $c 确定是否需要重新编译htm模板
//
// 解析htm模板文件
//
// 返回解析的结果, 用于直接输出到客户端
function &_ParseHTM( $f, $c = FALSE )
{
if ( $c )
{
$f = $this->_CompileHTM( $f );
}
else
{
$f = $this->_cache_dir.$this->_root_dir.'/'.TPL_COMPLIE_FILE_PREFIX.$this->_file;
}
return $this->_ParsePHP( $f );
}

// Private function
//
// 参数:
// $f 为HTM类型模板完整路径文件名
//
// 编译htm模板文件
//
// 编译htm模板文件,将存贮到缓存目录中
// 同时返回编译后的文件名
//
function &_CompileHTM( $f )
{
if ( !file_exists( $f ) )
{
die('Open file '.$f.' failed !');
}
ob_start();
$fp = fopen( $f, 'r');
$c = fread($fp, filesize($f));

// 屏蔽php代码
$c = preg_replace('/(\<\?)(.*)(\?\>)/siU', '<!---->', $c);

$c = preg_replace('/<!---->/', '<!---->} ?>', $c);
$c = preg_replace('/<!---->/', '<!---->} ?>', $c);
$p = array(
0 => '/\{([^}]+)\}/',
1 => '/<!---->/',
2 => '/<!---->/',
3 => '/<!---->/',
4 => '/<!---->/',
);
$s = array(
0 => '<!---->\$\1?>',
1 => '<!---->\$\1) { ?>',
2 => '<!---->\$\1 as \$\2 ) { ?>',
3 => '<!---->\$\1 \2 \$\3) { ?>',
4 => '<!---->\$\1 as \$\2 => \$\3 ) { ?>',
);
echo $c = preg_replace($p, $s, $c);
$c = &ob_get_contents();
ob_end_clean();
// 生成需要创建的缓存目录
$d = $this->_cache_dir.$this->_root_dir;
$this->_MakeDirectory( $d );
// 创建编译后的模板文件
$cf = $d.'/'.TPL_COMPLIE_FILE_PREFIX.$this->_file;
if(!@$fp = fopen($cf, 'w'))
{
die('Open file '.$cf.' failed !');
}
flock( $fp, 3 );
fwrite($fp, $c);
fclose($fp);
return $cf;
}

// Private function
//
// 参数
// $d 要创建的目录名
//
// 创建目录
//
function _MakeDirectory( $d )
{
if (is_null($d))
{
return TRUE;
}
$p = explode('/', $d);
foreach ( $p as $k => $v )
{
$prefix .= $v.'/';
if ( is_dir( $prefix ) )
continue;
if (!empty($v) && !@mkdir($prefix, 0777))
die('Cant create cache dir : '.$prefix);
}
return TRUE;
}

/******************************************************************************************/

// 公共成员方法 调用接口
// 初始化成员变量
function Template() {}

// public function
//
// 参数:
// $d 缓存目录路径
//
// 设置缓存和编译文件存放目录
//
function SetCacheDir( $d )
{
$this->_cache_dir = $d;
return TRUE;
}

// Public function
//
// 参数:
// $f 模板文件存放的完整路径名
// $t 模板类型
// TPL_HTM
// TPL_PHP
//
// 设置模板文件存放的目录和文件名以及模板的类型
//
function SetFile( $f = NULL, $t = TPL_HTM )
{
$this->_root_dir = dirname($f);
$this->_file = basename($f);
$this->_file_type = $t;
return TRUE;
}

// Public function
//
// 参数:
// $n 可以为 模板内在{}号内定义的名称
// 或为数组
// $n[]['id'], $n[]['name'], $n[]['sex']
//
// $v 当 $n 为数组时, $v 为空值
//
// 设置模板内定义变量
//
function SetVar( $n, $v = NULL )
{
if ( is_array( $n ) )
{
foreach ( $n as $k => $v )
{
$this->_var[$k] = $v;
}
}
else
{
$this->_var[$n] = $v;
}
return TRUE;
}

// Public function
//
// 参数说明:
// $t 为处理的模板的类型
//
// 对指定的模板进行处理解析 根据 $t 的类型返回不同的结果
//
// $t == TPL_PHP 立即解析返回 html 文件 ( parse -> result )
// $t == TPL_HTM 立即解析返回 html 文件 ( compile -> cache compiled -> parse -> result )
//
// $e == TRUE 时重新编译模板文件 FALSE 使用上一次的编译过的文件
//
function &Parse( $t, $e = FALSE)
{
switch ( $t )
{
case TPL_PHP :
$c = $this->_ParsePHP( $this->_root_dir.'/'.$this->_file );
break;
case TPL_HTM :
$c = $this->_ParseHTM( $this->_root_dir.'/'.$this->_file, $e );
break;
}
return $c;
}
}
?>
分享到:
评论

相关推荐

    一个string模板类

    综上所述,这个自定义的`string`类模板旨在提供一个高效、灵活且易用的字符串处理工具,其设计和实现涉及到了C++模板、内存管理、运算符重载、字符串算法、迭代器、编码处理、异常安全以及线程安全等多个核心知识点...

    一个简洁、易用的美赛 LaTeX 模板.zip

    "一个简洁、易用的美赛 LaTeX 模板.zip" 提供了一个专为美赛设计的模板,可以帮助参赛者快速构建专业、格式规范的论文。 该模板的特点在于简洁性和易用性,这使得参赛者可以更专注于模型构建和数据分析,而不用在...

    小程序模板消息

    描述中提到的“封装了小程序在后台向微信推送消息的过程”,意味着开发人员已经将复杂的接口调用和数据处理封装成一个易用的模块,简化了开发流程。这样,开发者无需深入了解微信小程序的底层机制,也能轻松实现模板...

    【T29298】响应式网站建设小程序开发类网站模板(自适应手机端).zip

    "【T29298】响应式网站建设小程序开发类网站模板(自适应手机端)" 是一个针对此类需求设计的资源包,它包含了一系列用于构建响应式网站和小程序的元素和文件。 1. **响应式设计**:响应式网站设计是一种使网站在不同...

    简单易用的前端模板预编译工具

    5. **Nunjucks**:Nunjucks是另一个功能丰富的模板引擎,提供了丰富的内建过滤器、标签和宏,支持自定义模板路径和命名空间。 五、应用场景 前端模板预编译工具广泛应用于SPA(单页应用)、服务器端渲染、邮件模板...

    Plates:一个原始的PHP模板库

    Plates是一个轻量级、易用且高效的PHP模板库,旨在简化Web开发中的视图层处理。它提供了一种清晰的语法,使得开发者能够更专注于创建干净、可读性强的HTML代码,而无需被复杂的模板引擎语法所困扰。下面将详细探讨...

    时尚小型商品电子商务网站模板

    "时尚小型商品电子商务网站模板"则专为那些经营时尚类小商品的企业或个人设计,旨在打造一个既具有潮流感又易于操作的在线店铺。 在设计上,此类模板通常会注重以下几个方面: 1. **视觉效果**:时尚元素的融入是...

    图像处理网站搭建模板设计,视频剪辑网站素材必备

    在构建一个专业的图像处理和视频剪辑网站时,选择合适的模板设计至关重要。这款"图像处理网站搭建模板设计,视频剪辑网站素材必备"提供了一整套高质量的UI界面,为创建一个高端大气、功能丰富的在线平台奠定了基础。...

    商城和官网类模板.zip

    标题 "商城和官网类模板.zip" 提供了一个关于PC端网页设计的资源,它是一个用于构建电子商务商城或官方网站的简洁模板。这个模板基于Vue.js框架,并利用了Element-UI库来实现用户界面组件。让我们深入了解一下这个...

    C++类模板&&容器&&重载

    类模板是C++中的一个关键特性,它允许我们创建泛型类,也就是可以处理不同类型数据的类。类模板定义了类的一般结构,但不包含具体的类型。当你实例化模板时,你可以提供具体的类型参数,这样编译器就会生成一个特定...

    (自适应手机端)响应式人力资源服务类网站pbootcms模板 企业管理网站源码

    PbootCMS是一个轻量级的PHP建站系统,以其快速、稳定、易用的特点在众多CMS中脱颖而出。 该模板适用于构建企业管理类网站,特别是人力资源服务相关的业务,如招聘、培训、咨询等。通过此模板,企业可以方便地展示其...

    CArray模板类的应用举例

    总的来说,CArray模板类是MFC编程中处理动态数据集合的重要工具,它的灵活性和易用性使得在处理数组操作时更加高效便捷。熟练掌握CArray的使用,能极大地提高你的C++编程效率,尤其是在处理大量数据时。

    CRMEB_PRO_生鲜优选模板v1.3,uinapp生鲜商城模板

    这个模板包含了完整的前端界面和可能需要的后台逻辑,旨在提供一个高效、易用且功能丰富的平台,以满足用户在线购买生鲜商品的需求。 1. **uni-app框架**: uni-app是一个使用Vue.js开发的多端框架,它支持编写一...

    仿赶集网站模板.net分类信息管理系统下载

    一个功能强大的分类信息(广告)系统,网软志成分类信息网正式版下载,地方门户系统,分类信息网模板,分类信息网淡红色风格版下载,仿快点8分类信息网门户网站系统源码,供求信息发布网站系统和信息发布网站程序,漂亮的...

    爱情交友婚介类CSS模板_爱情 交友 婚介 蓝色 love_html网站模板_网页源码移动端前端_H5模板_自适应响应.rar

    这个模板旨在为在线婚介平台提供一个吸引用户、展示信息并促进互动的界面。接下来,我们将详细讨论这个模板中涉及的IT知识点。 1. **CSS模板**:CSS(Cascading Style Sheets)是一种样式表语言,用于描述HTML或XML...

    Go-Hero一个方便快速强大的模板引擎

    Go-Hero模板引擎是一款专为Go语言开发者设计的高效、便捷且功能强大的工具,它主要用于构建Web应用中的视图层。Hero引擎通过预编译HTML模板到Go代码...如果你正在寻找一个Go语言的模板解决方案,Go-Hero绝对值得尝试。

    万能网站模板(方便快捷)已经测试

    【万能网站模板(方便快捷)已经测试】这个标题揭示了我们讨论的核心——一个通用的、易用且高效的网站模板,它已经过测试并证明其功能性和稳定性。这个模板可能是为了帮助网页设计师或开发者快速搭建网站,减少从零...

    HTML5教育类网站模板是一款适合教育培训类网站模板 .rar

    3. 响应式设计:考虑到用户可能使用不同设备访问网站,如电脑、平板和手机,一个好的教育类网站模板会采用响应式设计。这意味着网站布局和样式会根据用户的设备屏幕大小自动调整,确保在任何设备上都能提供良好的...

    8套html5后台模板精美易用

    5. **jQuery和其他JS库**:jQuery是一个快速、简洁的JavaScript库,使得DOM操作、事件处理和动画变得简单。这些后台模板可能集成jQuery以及其他JS库如jQuery UI、Moment.js等,用于增强交互性和功能性。 6. **图表...

    PHP的常用的几大模板引擎

    - ShellPage是一个简单易用的模板类,可以让整个网站的布局基于模板文件进行构建,通过修改模板文件即可实现对整个站点布局的调整。 - 支持多语言、多主题切换等功能,非常适合需要频繁更新设计风格的项目。 - **...

Global site tag (gtag.js) - Google Analytics