【发布时间】:2014-05-18 11:01:35
【问题描述】:
我正在开发一个模板引擎(我不想使用已经存在的引擎),它运行良好。这是我现在的代码:
class template {
private $vars = array();
public $page;
function __construct() {
}
public function render($render = false) {
$page = $this->page . '.php';
$content = file_get_contents($page);
foreach ($this->vars as $key => $value) {
$tag = '{' . $key . '}';
$content = str_replace($tag, $value, $content);
}
if ($render)
echo $content;
else
return $content;
}
public function assign($key, $value, $overwrite = false) {
if ($overwrite) {
$this->vars[$key] = $value;
} else if (isset($this->vars[$key])) {
echo 'this var already exists!';
} else {
$this->vars[$key] = $value;
}
}
public function append($key, $value) {
$this->vars[$key] .= $value;
}
public function setPage($page) {
$this->page = $page;
}
}
但我想知道如何将 if & else 和 foreach 循环添加到引擎中。我希望它在 html 中看起来像这样:
<!DOCTYPE html>
<html>
<head></head>
<body>
[@if {bool} == true][ <!-- different expressions like {int} > 2 should work too -->
<div>{text}</div>
]
[@else][
<div> error </div>
]
[@foreach {jsLinks} as {jsLink}][
<script type="text/javascript" src="{jsLink}"></script>
]
</body>
</html>
模板文件保存为 .php 文件,所以我可以这样做<?php if($bool == true){?> some html <?php }?>,
但我不想在模板文件中使用 php 代码。
谁能帮我解决这个问题?
编辑
我添加了这段代码:
$content = preg_replace('~\{LOOP:(\w+)\}~', '<?php foreach ($this->vars[\'$1\'] as $ELEMENT): $this->wrap($ELEMENT); ?>', $content);
$content = preg_replace('~\{ENDLOOP:(\w+)\}~', '<?php $this->unwrap(); endforeach; ?>', $content);
还有这两个功能:
private function wrap($element){
$this->stack[] = $this->vars;
foreach ($element as $k => $v) {
$this->vars[$k] = $v;
}
}
private function unwrap() {
$this->vars = array_pop($this->stack);
}
但这只是在浏览器中回显<?php foreach ($this->vars[\'$1\'] as $ELEMENT): $this->wrap($ELEMENT); ?> 和<?php $this->unwrap(); endforeach; ?>。有什么办法解决这个问题?
编辑:我做到了!
我现在可以在我的模板中使用 foreach 循环以及 if 和 else。我的模板类:
<?php
class Template {
private $vars = array();
public $page;
public $view;
public $bDisplay = true;
function __construct($view = false) {
$this->view = $view;
}
public function render($render = false) {
if ($this->bDisplay === true) {
$page = PATH_VIEWS . $this->page . '.php';
$page = (empty($this->page) ? ($this->view ? PATH_VIEWS . $this->view . DS . 'index.php' : PATH_VIEWS . 'index' . DS . 'index.php') : (file_exists($page) ? $page : PATH_VIEWS . 'index' . DS . 'index.php'));
$content = file_get_contents($page);
$content = $this->replace($content, $this->vars);
$content = preg_replace('~\{LOOP:(\w+)\}~', '<?php foreach ($this->vars[\'$1\'] as $value){ echo $this->replace(\'', $content);
$content = preg_replace('~\{ENDLOOP:(\w+)\}~', '\', $value);} ?>', $content);
$content = preg_replace('~\{IF:([^\r\n}]+)\}~', '<?php if ($1): echo \'', $content);
$content = preg_replace('~\{ELSE\}~', '\'; else: echo \'', $content);
$content = preg_replace('~\{ENDIF\}~', '\'; endif; ?>', $content);
if ($render)
eval('?>' . $content . '<?php');
else
return $content;
}
else {
return false;
}
}
private function replace($content, $vars) {
foreach ($vars as $key => $value) {
if (!is_array($vars[$key])) {
$tag = '{' . $key . '}';
$content = str_replace($tag, $value, $content);
}
}
return $content;
}
public function assign($key, $value, $overwrite = false) {
if ($overwrite) {
$this->vars[$key] = $value;
} else if (isset($this->vars[$key])) {
echo 'this var already exists!';
} else {
$this->vars[$key] = $value;
}
}
public function append($key, $value) {
$this->vars[$key] .= $value;
}
public function addArray($array, $key, $value) {
$this->vars[$array][][$key] = $value;
}
public function setPage($page) {
$this->page = $page;
}
}
?>
以模板为例:
<!DOCTYPE html>
<html>
<head></head>
<body>
<!-- foreach loops -->
{LOOP:js}
<script type="text/javascript" src="{link}"></script>
{ENDLOOP}
<!-- if statement -->
{IF: {bool} === true}
display some text
{ENDIF}
<!-- if-else statement -->
{IF: {number} > 2}
number is bigger than 2
{ELSE}
number is smaller than 2
{ENDIF}
</body>
</html>
【问题讨论】:
-
您需要实现一个解析器,或者更好的转换器,并将其注册为这些模板文件的处理程序。您可能想查看在 unixoid 系统上常见的“编译器编译器”:
bison和yacc。
标签: php html if-statement foreach template-engine