简单的PHP模板,续 背景
因此,我询问了PHP模板,我得到了很多回复,如:简单的PHP模板,续 背景,php,regex,templates,Php,Regex,Templates,因此,我询问了PHP模板,我得到了很多回复,如: 它是不需要的;PHP本身就是一种很好的模板语言 很难开发一种强大且易于设计师使用(或使用)的模板语言 已经完成了,请使用模板框架X 你真蠢 所有这些观点都有一定的正确性。记住他们,我继续做模板制作,现在我回来问更多的问题。:) 概述 目标 以下是此模板引擎的目标: 最小语法 生成干净的php代码 不要破坏html语法突出显示 php开发人员不需要学习任何新的东西(嗯,不需要太多) 支持大部分php流控制(除了do..while之外的所有功
- 它是不需要的;PHP本身就是一种很好的模板语言
- 很难开发一种强大且易于设计师使用(或使用)的模板语言
- 已经完成了,请使用模板框架X
- 你真蠢
目标 以下是此模板引擎的目标:
- 最小语法
- 生成干净的php代码
- 不要破坏html语法突出显示
- php开发人员不需要学习任何新的东西(嗯,不需要太多)
- 支持大部分php流控制(除了do..while之外的所有功能)
- 支持内联php
- 默认转义序列是
*{…}
- 如果没有其他规则匹配,则回显或评估序列
- 如果序列以分号结尾,则计算整个序列
- 否则,回显第一个表达式并计算其余表达式
- 如果没有其他规则匹配,则回显或评估序列
开始一个块。{{for | foreach | if | switch | while(…):}}
- 条件中的括号可以省略
- 冒号可以省略
- 支架匹配时可省略右外支架**
做你想做的事。{{else | elseif | break | continue | case | default}}
- 条件中的括号可以省略
- 在
上可以省略右外括号以进行括号匹配{case}
- 在{break | continue}}上可以省略左外括号以进行括号匹配
结束一个块。{{end}}
- 单词字符可以附加到“end”,例如“end\u if”
- 支架匹配时,可省略左外支架
**可以禁用括号匹配语法。 模板 到目前为止,我们已经为
和
提出了一种替换语法。为了使它真正有用,我们需要一些特定于模板的操作
我使用的另一个模板框架使用了一个简单的容器/内容范例,在这里应该可以很好地工作。模板系统是基于xml的,所以代码看起来像这样
<!-- in a template -->
<html>
<head>
<tt:Container name="script" />
</head>
<body>
<tt:Container name="main" />
</body>
</html>
<!-- in a page -->
<tt:Content name="script">
<script src="foo.js"></script>
</tt:Content>
<tt:Content name="main">
<div>...</div>
</tt:Content>
模板化html示例:
<script>var _lang = {{json_encode($lang)}};</script>
<script src='/cartel/static/inventory.js'></script>
<link href='/cartel/static/inventory.css' type='text/css' rel='stylesheet' />
<form class="inquiry" method="post" action="process.php" onsubmit="return validate(this)">
<div class="filter">
<h2>{{$lang['T_FILTER_TITLE']}}</h2>
<a href='#{{urlencode($lang['T_FILTER_ALL'])}}' onclick='applyFilter();'>{{$lang['T_FILTER_ALL']}}</a>
{{foreach ($filters as $f)}}
<a href='#{{urlencode($f)}}' onclick='applyFilter("c_{{urlencode($f)}}");'>{{$f}}</a>
{{end}}
</div>
<table class="inventory" id="inventory_table">
{{foreach $row_array as $row_num=>$r}
{{if $row_num==0}
<tr class='static'>
{{foreach $r as $col}
<th>{{$col}}</th>
{end}}
<th class='ordercol'>{{$lang['T_ORDER']}}</th>
</tr>
{{else}}
{{function spin_button $id, $dir, $max}
<a href='#' class='spinbutton'
onclick="return spin('{{$id}}', {{$dir}}, {{$max}})">
{{$dir==-1 ? '◀' : '▶'}}
</a>
{end}}
<tr class="{{'c_'.urlencode($r[$man_col])}}">
{{foreach $r as $i=>$col}
<td class='{{$i?"col":"firstcol"}}'>{{$col}}</td>
{end}}
<td class='ordercol'>
{{$id="part_{$r[$part_col]}"; $max=$r[$qty_col];}}
{{spin_button($id, -1, $max)}}
<input onchange="spin(this.id, 0, '{{$max}}')"
id='{{$id}}' name='{{$id}}'type='text' value='0' />
{{spin_button($id, +1, $max)}}
</td>
</tr>
{end}}
{end}}
<tr class="static"><th colspan="{{$cols+1}}">{{$lang['T_FORM_HELP']}}</th></tr>
{{foreach $fields as $f}
<tr class="static">
<td class="fields" colspan="2">
<label for="{{$f[0]}}">{{$f[1]}}</label>
</td>
<td class="fields" colspan="{{$cols-1}}">
<input name="{{$f[0]}}" id="{{$f[0]}}" type="text" />
</td>
</tr>
{end}}
<tr class="static">
<td id="validation" class="send" colspan="{{$cols}}"> </td>
<td colspan="1" class="send"><input type="submit" value="{{$lang['T_SEND']}}" /></td>
</tr>
</table>
</form>
var\u lang={{json\u encode($lang)};
{{$lang['T_FILTER_TITLE']}
{{foreach($f作为过滤器)}
{{end}
{{foreach$row_数组作为$row_num=>$r}
{{如果$row_num==0}
{{foreach$r as$col}
{{$col}}
{end}
{{$lang['T_ORDER']}
{{else}
{{函数自旋按钮$id,$dir,$max}
{end}
{{foreach$r as$i=>$col}
{{$col}}
{end}
{{$id=“part{$r[$part\u col]}”;$max=$r[$qty\u col];}
{{spin_按钮($id,-1,$max)}
{{spin_按钮($id,+1,$max)}
{end}
{end}
{{$lang['T_FORM_HELP']}
{{foreach$字段作为$f}
{{$f[1]}
{end}
问题
我有几个问题要问如何继续这件事。有些人有明确的答案,有些人可能更喜欢CW材料
- set/get生成混乱的代码。可以改进吗?我在set/get和
之间寻找某种合理的中间立场(参见代码和示例){{function}}
- 流行模板语言中缺少什么
- 语法正确吗?回应事物的线条、做事情的线条和流量控制线条在语法上是否应该更为不同?那么可选的外支架如何匹配。。。傻
和
生成干净的php代码
我觉得这不太干净
不要破坏html语法突出显示
您正在破坏PHP语法突出显示,我发现这比破坏HTML语法突出显示问题更大。如果你能找到一个更好的编辑器来理解PHP和HTML是如何交互的(我使用Textmate),这就不必担心了
php开发人员不需要学习任何新的东西(嗯,不需要太多)
普通PHP已经合格
支持大部分php流控制(除了do..while之外的所有功能)
普通PHP支持所有PHP流控制
支持内联php
普通PHP支持内联PHP
总之,我认为这种方法没有任何好处,当然也没有超过成熟的现有PHP框架和模板引擎
最小语法
和
生成干净的php代码
我觉得这不太干净
不要破坏html语法突出显示
您正在破坏PHP语法突出显示,我发现这比破坏HTML语法突出显示问题更大。如果你能找到一个更好的编辑器来理解PHP和HTML是如何交互的(我使用Textmate),这就不必担心了
php开发人员不需要学习任何新的东西(嗯,不需要太多)
普通PHP已经合格
支持大部分php流控制(除了do..while之外的所有功能)
普通PHP支持所有PHP流控制
支持内联php
普通PHP支持内联PHP
总之,我认为这种方法没有任何好处,当然也没有超过成熟的现有PHP框架和模板引擎。。。不能理解
<script src="bar.js"></script>
<script src="foo.js"></script>
<?php
class Detemplate {
public $container_prefix='_tpl_';
public $brackets='{}';
public $bracket_matching=true;
public $use_cache=false;
private $block_keywords=array('for','foreach','if','switch','while');
private $set_count;
private $get_count;
public function parse_file ($file, $vars=array()) {
$sha1=sha1($file);
$cache = dirname(__FILE__)."/cache/".basename($file).".$sha1.php";
$f = "{$this->container_prefix}page_{$sha1}_";
if (!$this->use_cache || !file_exists($cache) || filemtime($cache)<filemtime($file)) {
$php = "<?php function $f {$this->t_vars()} ?>".
$this->parse_markup(file_get_contents($file)).
"<?php } ?>";
file_put_contents($cache, $php);
}
include $cache;
$f($vars);
}
public function parse_markup ($markup) {
$blocks=implode('|', $this->block_keywords);
$arglist= '\s*[\s(](.*?)\)?\s*'; // capture an argument list
$word= '\s*(\w+)\s*'; // capture a single word
$l='\\'.$this->brackets{0}; // left bracket
$r='\\'.$this->brackets{1}; // right bracket
$dl="#$l$l";
$sl=$this->bracket_matching ? "#$l?$l" : $dl;
$dr="$r$r(?!:$r)#";
$sr=$this->bracket_matching ? "$r$r?(?!:$r)#" : $dr;
$markup=preg_replace_callback(
array (
$sl.'(end)[_\w]*\s*;?\s*'.$dr,
$dl.'(el)se\s*if'.$arglist.':?\s*'.$dr,
$dl.'(else)\s*:?\s*'.$dr,
$dl.'(case)'.$word.':?\s*'.$sr,
$dl.'(default)()\s*:?\s*'.$sr,
$sl.'(break|continue)\s*;?\s*'.$dr,
$dl.'(set)'.$word.':?\s*'.$sr,
$dl.'(get)'.$word.':?\s*'.$dr,
$dl.'(parse)'.$word.':?\s*'.$dr,
$dl.'(function|fn)'.$word.$arglist.':?\s*'.$sr,
$dl.'('.$blocks.')'.$arglist.':?\s*'.$sr,
'#('.$l.$l.')(.+?)(;?)\s*'.$dr,
'#\s*(\?)>[\s\n]*<\?php\s*#',
),
array($this, 'preg_callback'),
$markup);
return $markup;
}
private function preg_callback ($m) {
switch ($m[1]) {
// end of block
case "end":
return "<?php } } ?>";
// keywords with special handling
case "el": // elseif
return "<?php } elseif ({$m[2]}) { ?>";
case "else":
return "<?php } else { ?>";
case "case": case "default":
return "<?php {$m[1]} {$m[2]}: ?>";
case "break": case "continue":
return "<?php {$m[1]}; ?>";
// parse an external template document
case "parse":
return $this->parse_markup(file_get_contents($m[2]));
// save / load content sections
case "set":
$i=++$this->set_count[$m[2]];
$f=$this->t_fn($m[2], $i);
$p=$this->t_fn($m[2], $i-1);
$v=$this->t_fn_alias($m[2]);
return "<?php if (!function_exists('$f')) { $v='$f'; ".
"function $f {$this->t_vars()} unset ($v); $v='$p'; ?>";
case "get":
$i=++$this->get_count[$m[2]];
$c=$this->t_fn_ctx($m[2], $i);
$v=$this->t_tmp();
$a=$this->t_fn_alias($m[2]);
return "<?php if (!$c) { ".
"foreach (array_keys(get_defined_vars()) as $v) $c".
"[$v]=&\$$v; unset($v); } $a(&$c); ?>";
case "function": case "fn":
return "<?php if (!function_exists('{$m[2]}')) { ".
"function {$m[2]} ({$m[3]}) { ?>";
// echo / interpret
case "{{":
return "<?php".($m[3]?"":" echo")." {$m[2]}; ?>";
// merge adjacent php tags
case "?":
return " ";
}
// block keywords
if (in_array($m[1], $this->block_keywords)) {
return "<?php { {$m[1]} ({$m[2]}) { ?>";
}
}
private function t_fn ($name, $index) {
if ($index<1) return "is_null";
return "{$this->container_prefix}{$name}_$index";
}
private function t_fn_alias ($name) {
return "\${$this->container_prefix}['fn_$name']";
}
private function t_fn_ctx ($name, $index) {
return "\${$this->container_prefix}['ctx_{$name}_$index']";
}
private function t_vars () {
$v=$this->t_tmp();
return "($v) { extract($v); unset($v);";
}
private function t_tmp () {
return '$'.$this->container_prefix.'v';
}
}
?>
<script>var _lang = {{json_encode($lang)}};</script>
<script src='/cartel/static/inventory.js'></script>
<link href='/cartel/static/inventory.css' type='text/css' rel='stylesheet' />
<form class="inquiry" method="post" action="process.php" onsubmit="return validate(this)">
<div class="filter">
<h2>{{$lang['T_FILTER_TITLE']}}</h2>
<a href='#{{urlencode($lang['T_FILTER_ALL'])}}' onclick='applyFilter();'>{{$lang['T_FILTER_ALL']}}</a>
{{foreach ($filters as $f)}}
<a href='#{{urlencode($f)}}' onclick='applyFilter("c_{{urlencode($f)}}");'>{{$f}}</a>
{{end}}
</div>
<table class="inventory" id="inventory_table">
{{foreach $row_array as $row_num=>$r}
{{if $row_num==0}
<tr class='static'>
{{foreach $r as $col}
<th>{{$col}}</th>
{end}}
<th class='ordercol'>{{$lang['T_ORDER']}}</th>
</tr>
{{else}}
{{function spin_button $id, $dir, $max}
<a href='#' class='spinbutton'
onclick="return spin('{{$id}}', {{$dir}}, {{$max}})">
{{$dir==-1 ? '◀' : '▶'}}
</a>
{end}}
<tr class="{{'c_'.urlencode($r[$man_col])}}">
{{foreach $r as $i=>$col}
<td class='{{$i?"col":"firstcol"}}'>{{$col}}</td>
{end}}
<td class='ordercol'>
{{$id="part_{$r[$part_col]}"; $max=$r[$qty_col];}}
{{spin_button($id, -1, $max)}}
<input onchange="spin(this.id, 0, '{{$max}}')"
id='{{$id}}' name='{{$id}}'type='text' value='0' />
{{spin_button($id, +1, $max)}}
</td>
</tr>
{end}}
{end}}
<tr class="static"><th colspan="{{$cols+1}}">{{$lang['T_FORM_HELP']}}</th></tr>
{{foreach $fields as $f}
<tr class="static">
<td class="fields" colspan="2">
<label for="{{$f[0]}}">{{$f[1]}}</label>
</td>
<td class="fields" colspan="{{$cols-1}}">
<input name="{{$f[0]}}" id="{{$f[0]}}" type="text" />
</td>
</tr>
{end}}
<tr class="static">
<td id="validation" class="send" colspan="{{$cols}}"> </td>
<td colspan="1" class="send"><input type="submit" value="{{$lang['T_SEND']}}" /></td>
</tr>
</table>
</form>