喜悦国际村 专业PHP开发者社区's Archiver

stanley.wy 发表于 2010-3-20 10:37 PM

模板应用:"模板语法"与"PHP原生语法"

[quote][color=red]竟然不能上传图片和附件,只好链到别人的论坛。非广告。[/color][/quote]

[quote]长年伏案从事PHP代码编写,总认为PHP一切都是最好的,总是脱离不了各种流行的代码的思想,自己写个框架结果却与ZEND、THINK之类90%相象,写个模板处理又脱离不了SMARTY的语法和结构,发誓要写个完全属于自己的东西,最终还是没有跳出JAVA的那种模式,总之感觉一切都模仿,却又跳不出怪圈。恼!
[/quote]

公司有一个叫Lucas的页面美工。
Lucas:“为什么你们PHP程序员把我的页面拿去改一下,我在浏览器中就什么也显示不了?”。
我:“因为我们已经把它改成了Smarty的模板了,便于开发!”。
Lucas:“Smarty是什么?”
我:“是一种用于处理WEB页面的模板引擎,非常强大,专门用于美工的前台页面开发!”。
Lucas:“哦,那看来我需要下载资料看看。"

N天后。

Lucas:“Smarty好麻烦呀,要学一大堆的语法。”
我:“还行吧!”
Lucas:“可是我这些天却把PHP的基本语法给看懂了!”
我:“恭喜恭喜”
Lucas:“可是为什么不能直接用PHP代码做模板语言呢?为什么非要创造出一个{}这样的语法,而不用<?php ?>这样的结构呢?”
我:“这是为了便于MVC的”;
Lucase:“使用<?php ?>就不便于MVC了?”。
我很困惑:“似乎也没有什么不可,不过Smarty是PHP里最常被使用的模板引擎,你不用质疑。”。
Lucas:“最常被使用?,IE6难道不是最常被使用,可是我最痛恨IE6”。
我:“我也一样痛恨IE6”。
Lucas:“那是否可以帮我写一个程序,直接使用<?php ?>这样的结构模板?”。
我:“直接使用<?php ?>这样不是很安全,如果有人在模板中写入了恶意代码那结果很严重!”。
Lucas:“那你难道不能过滤一下?”
我:“确实可以!”
Lucas:“等你给我好消息!”。


[color=red]仔细一想,确实使用<?php ?>与使用{}这样的结构对于模板处理来说,并没有什么异同,可是究竟是什么让我相信Smarty。在同事的拜托下,决定写一个处理模板的程序,希望实现下面的功能 :
1.直接使用PHP的程序引用作为模板语法引用。即直接使用<?php ?>这样的结构。
2.直接使用echo、if、for、foreach等等PHP的语法,而不去创造新的语法。
3.最关键的是直接打开模板文件,在浏览器中呈现的样式与PHP处理过的样式完全一致。
4.能够指定使用哪些函数,同时不能使用哪些函数。
5.禁止在模板中定义函数,定义类。
6.禁止使用特殊的函数调用方法,强调安全。如:“$a = 'phpinfo'; $a();”这样的写法。
7.程序要简单极简单。[/color]

花了一个小时左右,将工作成果展示如下,希望PHP的高手能够指点,继续优化程序。

html源代码:
[code]
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd]http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<link type="text/css" rel="stylesheet" href="$css/style.css" />
<title><!--<?php echo $sitename ?>--></title>
</head>
<body>
<img src="$imgs/logo.gif" />
<br /><br />
<div id="nav">
<ul>
  <!--<?php foreach ($list as $k => $v) { ?>-->
  <li><a href="read.php?id=<!--<?php echo $k; ?>-->"><!--<?php echo $v; ?>--></a></li>
  <!--<?php } ?>-->
</ul>
</div>
<br /><br />
这里调用了一个函数strlen:<br />
计算stanley.wy字符串长度:<?php echo strlen('stanley.wy'); ?>
<br /><br />
<? echo '今天的日期是:',date('Y-m-d'); ?>
<br />
</body>
</html>
[/code]
在代码中使用<!-- <? php ?>-->方式使用php代码 ,当然也可以直接使用<? php ?>,但是使用<!--< php ?>-->的方法好处在于,在直接在浏览器中游览时会把<!--<? php ?>-->当成是注释,从而不显示,防止破坏美工在工具软件下查看文件页面。 另外,还使用$imgs,$css作为目录名称在后面非常好用,当然也可以换成别得字串。(这种方法源自非常早的一个PHPER的贴子,借用一下方法)

直接浏览显示的结果:
[img]http://www.happywork.me/!bbs/attachments/month_1003/10032022258575a2f3a5a6bf15.gif[/img]

页面调用程序 :
[code]
<?php
require_once('tpl.inc.php');
$sitename = '试一下看看';
$list = array(
'开源软件未来发展趋势:更少利润,更多理念',
'讲解MySQL的数据类型和建库策略',
'简介SQL Server 2008的变更跟踪',
'开源数据库Sharding技术',
'W3C 接连推出 7 个 HTML 草案',
'关于json template一点思考',
'jquery-easyui 名片管理系统',
);
//实例模板类
$t = new wyTpl();
//配置图像路径
$t->imgs = 'tpls/$imgs';
//配置样式表存贮路径
$t->css = 'tpls/$css';
//载入模板文件
include($t->tpl('tpls/index.html'));
?>
[/code]
模板处理程序,能够过滤所有不安全的变量调用如$_SERVER这样的全局变量,同时还可以指定哪些函数是可以被使用的,还可以继续扩充:
[code]
<?php
$wyTpl_AllowFunctionList = array(
'strlen',
'date',
);
class wyTpl {
public $imgs;
public $css;
public $js;
public function tpl($tpl_file) {
  $target_file = 'cache/'.basename($tpl_file);
  if (@filemtime($tpl_file) < @filemtime($target_file)) return $target_file;
   
  $fp = fopen($tpl_file,'r');
  $content = fread($fp,filesize($tpl_file));
  fclose($fp);
  
  $content = str_replace('<!--<?php','<?php',$content);
  $content = str_replace('?>-->','?>',$content);
  $content = preg_replace('/<\?([^p]){1}/i','<?php\1',$content);
  $content = str_replace('$imgs',$this->imgs,$content);
  $content = str_replace('$css',$this->css,$content);
  $content = str_replace('$js',$this->js,$content);
  self::checkWord($content);
  
  
  $fp = fopen($target_file,'w');
  fwrite($fp,$content);
  fclose($fp);
  
  return $target_file;
}
public function checkWord($content) {
  $token = token_get_all($content);
  $line = count($token);
  for ($i=0;$i<$line;$i++) {
   switch ($token[$i][0]) {
    case T_CLASS :
    case T_FUNCTION :
    case T_REQUIRE :
    case T_REQUIRE_ONCE :
    case T_INCLUDE :
    case T_INCLUDE_ONCE :
    case T_FILE :
    case T_LINE :
    case T_FUNC_C :
    case T_CLASS_C :
    case T_METHOD_C :
     die('模板文件中使用了非法的PHP语句。');
     break;
    case T_STRING :
     if (!in_array($token[$i][1],$GLOBALS['wyTpl_AllowFunctionList'])) die('模板文件中使用了非法的PHP的函数。');
     break;
    case T_VARIABLE :
     if ($token[$i+1] == '(') die('2 Script to detect illegal!!!');
     if (!self::checkVariableName($token[$i][1])) die('模板文件中使用了非法的变量名。');
     break;
   }
  }
}
public function checkVariableName($name) {
  switch ($name) {
   case '$_SERVER' :
   case '$_COOKIE' :
   case '$_ENV' :
   case '$_FILES' :
   case '$_GET' :
   case '$_POST' :
   case '$_REQUEST' :
   case '$_SERVER' :
   case '$_SESSION' :
   case '$GLOBALS' :
   case '$HTTP_COOKIE_VARS' :
   case '$HTTP_ENV_VARS' :
   case '$HTTP_GET_VARS' :
   case '$HTTP_POST_FILES' :
   case '$HTTP_POST_VARS' :
   case '$HTTP_SERVER_VARS' :
   case '$HTTP_SESSION_VARS' :
    return false;
  }
  return true;
}
}
?>
[/code]
之前还想通过词义分析进行PHP代码过滤,由于时间较短,又急于实现Lucas的希望的需求,因此使用token_get_all()进行TOKEN分析,使用数组循环方式进行代码过滤,似乎效率较低。不过在模板所谓的“编译”阶段,慢一点又如何?

最终执行结果页面:
[img]http://www.happywork.me/!bbs/attachments/month_1003/10032022285379d53a3afdd5b9.gif[/img]

程序打包文件下载:
[url=http://www.happywork.me/!bbs/attachment.php?aid=MjR8YTg5ZDk3NjJ8MTI2OTA5NTMzNXxkZjM0aHQ5eFZVaXhGUzVVWjdRYmZOOEZqMHRKb0VOUmtza1Z2U1BFZGNFSU1RMA%3D%3D]http://www.happywork.me/!bbs/attachment.php?aid=MjR8YTg5ZDk3NjJ8MTI2OTA5NTMzNXxkZjM0aHQ5eFZVaXhGUzVVWjdRYmZOOEZqMHRKb0VOUmtza1Z2U1BFZGNFSU1RMA%3D%3D[/url]

电脑民工 发表于 2010-3-21 05:31 PM

[b] [url=http://www.phpx.com/redirect.php?goto=findpost&pid=1147520&ptid=260019]1#[/url] [i]stanley.wy[/i] [/b]

近来我也一直在思考模版问题. 我的看法是

1. smarty是毁誉参半的东西,我不敢完全否定.
smarty最让人受不了的是其额外的一套模版语法.并且我也认为,如果美工能学会smarty,应该也学会很多php了.为什么smarty要假想美工是连基本的php都学不会的,然后以一套怪异的方式来决定开发流程呢.  但是当前smarty新版本似乎是3.x,支持php原生语法了,国内对于smarty,还是停留在2.6的印象. 所以我也不敢说smarty不好,毕竟有很多人用,而且一直在更新,优点不只是个模版的.

2. 如果模版引擎工作原理大同小异, 提高多少工作效率可能只区别于对这个引擎的熟悉程度.
我观察了许多的模版工具,多数模版工具基本思想一样, 是在"模版文件"的制定位置上凿个"窟窿",给"窟窿"做上标记, 接着最重要的, 在处理数据的页面, 指定对应的模版文件,和指定对应的窟窿与数据. 本来这个过程从概念上说似乎已经没什么精简的余地,如果新的模版方式换汤不换药,其实也是一样打窟窿约暗号, 能提高多少工作效率,是一个问题.

3. 或许, 模版文件完全封装html的思路根本就是不对的!
MVC, 用模版的目的是什么呢? 简单点通俗点,是为了换个程序外观一样用程序. 但是现在web程序的美工和程序员的分界点应当在哪里呢?
很多模版引擎设想美工就是不应当会点php的,程序员就是完全不用管程序表现的, 这种设想, 可能从根本上就已经错了. 这年头JavaScript应用如火如荼, 页面表现与程序逻辑不是水火不容, 而是浑然天成. 这年头xhtml页面, 强调css+div,美工控制css,控制修饰的img,swf等,完成布局与修饰, 但程序员,php程序员,web程序设计者,难道就是个只会几句query和SQL,只会从数据库里读出数据的家伙?  出于现代化web程序需要,出于大量使用JavaScript的需要,html标签输出必须控制在程序员手里. 美工手里的,是份关于什么标签,id,class,大致布局的简要说明,美工自个一边修饰之就可以的. 所以我认为把html标签弄到一个模版文件里给美工一边玩去,这样本来就是错的.

4. 个人认为模版文件的思路要变,从整个一个html文件模版变成小的组件模版.
整个一个html模版文件的重用性太差了, 程序内容变下,模版也要搞过. 许多模版呆板得很, 就是根据基本的网页head,nav,content基本修饰下, 也搞不出复杂的页面表现效果. 但是倘若模版文件并不是一个个页面,粒度更小些,是一个个提供常用参数(如ul-li的n个li的n, 常见布局div的id)接口的组件,这样应该更方便,重用性更高. 比如可以实现ul-li模版文件,内置m种ul-li实现,加上其他组件的模版,就可以实现组件重用, 实现m*n*数量级的各组件组合,创造出无数眼花缭乱的应用.

楼主我是认真的回帖的, 我边思考边码字码了两个小时,希望你能考虑我的意见.

Ankyliu 发表于 2010-6-30 03:34 PM

WordPress 的模板类似,有做过滤吗?谁研究过?

zyf8985957 发表于 2010-7-1 09:58 PM

支持。。。。。好东西~~~~~~~~~~~

游戏人间 发表于 2010-7-1 11:04 PM

不做评论,仅仅路过

村长夫人 发表于 2010-7-2 10:37 AM

我见过使用php脚本文件作为 视图文件的程序
其实没啥 你在smarty中也可以写入恶意代码 其实是否使用smarty和恶意代码无关
smarty提供了一些常用的视图解决方案 简化了视图代码的编写(和原生的PHP比起来至少可以替换掉echo) 这才是我们需要的东西

newmewo 发表于 2010-7-3 04:04 PM

我觉得都是老话题了。

模板好处,肯定是有的。
如果说模板跟程序没关联。那是瞎说。
关系肯定很复杂。
之所以存在,
我认为目的就为一个。

如果单单用一个东西,那么多个人一起做事,每个人都有自己的一套思想,
并且也可以肯定每个人所用的方法在处理自己需要处理的部分是绝对的好。
不过既然是多个人做事,就不能谁做谁的,必须融合。
smarty 之类的,就是一个界定标准。 做 html表现层的注重在用smarty 上要用的让。也就是在 html 源码级别上要够结构化。
写php的,可以把中心放在在业务流程上。 把至于页面需要某个引导。 需要某个动态显示数据的东西,只告诉模板,需要哪些数据
使用的细节部分可以暂时先抛开, 中心放在业务处理上。

不过最终的目的是, 大家不能各顾各的。 必须要有一个相对的标准来配合工作。

zyf8985957 发表于 2010-7-28 06:49 AM

不过最终的目的是, 大家不能各顾各的。 必须要有一个相对的标准来配合工作。

tianfing 发表于 2010-8-1 12:46 PM

比较赞同民工说的第三条。

clonman 发表于 2010-8-24 12:39 PM

smarty模版还是很不错地,起码解决了 公司要人时候 需要会smarty模版等要求 哈哈

村长夫人 发表于 2010-8-24 02:30 PM

[quote]smarty模版还是很不错地,起码解决了 公司要人时候 需要会smarty模版等要求 哈哈
[size=2][color=#999999]clonman 发表于 2010-8-24 12:39 PM[/color] [url=http://www.phpx.com/redirect.php?goto=findpost&pid=1156048&ptid=260019][img]http://www.phpx.com/images/common/back.gif[/img][/url][/size][/quote]
我去4年前过这种公司面试 我就直接问他:“我不会smarty,你感觉smarty有啥好处” 他说:“你用过就知道了”
现在我会用smarty 也会用一些其他的PHP或者Javascript的视图产品 原则上 只要你约束好了 有没有smarty其实都一样
很多人即便用了smarty 也跟没用一样

freemouse 发表于 2010-8-26 01:15 PM

不错,学习了

剑枫 发表于 2010-9-21 04:09 PM

:lol个人不赞同模板嵌入逻辑,也不能嵌入变量。美工毕竟不是程序员,别难为人家了,我的模板类都是嵌入html标签,当然这些标签是自定的不是真正的html标签,至少美工可以在编辑器不影响视觉效果

金家劳工 发表于 2010-9-23 09:56 AM

现在我们这的情况是美工给好一个HTML页面后,其它的事情就是自己的了,,,,

页: [1]

Powered by Discuz! Archiver 7.0.0  © 2001-2009 Comsenz Inc.