如果你不想用 ThinkPHP 5Laravel 这些自带模板系统,只想用 PHP 原生写一个“最简单的模板引擎”,其实非常容易。

下面给你一个:

✅ 仅 50 行
✅ 支持变量替换
✅ 支持 if
✅ 支持 foreach
✅ 无依赖
✅ 适合学习原理


一、最最简单版本(变量替换版)

模板文件 view.html

<h1>{{title}}</h1>
<p>欢迎你,{{name}}</p>


模板引擎类 Template.php

<?php

class Template
{
    protected $vars = [];

    public function assign($key, $value)
    {
        $this->vars[$key] = $value;
    }

    public function render($file)
    {
        $content = file_get_contents($file);

        foreach ($this->vars as $key => $value) {
            $content = str_replace('{{'.$key.'}}', $value, $content);
        }

        echo $content;
    }
}


使用方式

require 'Template.php';

$tpl = new Template();
$tpl->assign('title', '我的首页');
$tpl->assign('name', '张三');
$tpl->render('view.html');


二、升级版(支持 if / foreach)

我们做一个“超轻量编译型模板引擎”。

原理:

把模板语法转换成 PHP 代码,然后 include 执行。


1️⃣ 模板文件 view.html

<h1>{$title}</h1>

{if $age >= 18}
<p>你是成年人</p>
{else}
<p>你是未成年</p>
{/if}

<ul>
{foreach $list as $item}
<li>{$item}</li>
{/foreach}
</ul>


2️⃣ 模板引擎

<?php

class Template
{
    protected $vars = [];
    protected $cachePath = 'cache/';

    public function assign($key, $value)
    {
        $this->vars[$key] = $value;
    }

    public function render($file)
    {
        $cacheFile = $this->cachePath . md5($file) . '.php';

        // 如果缓存不存在或模板更新
        if (!file_exists($cacheFile) || filemtime($file) > filemtime($cacheFile)) {
            $content = file_get_contents($file);
            $compiled = $this->compile($content);
            file_put_contents($cacheFile, $compiled);
        }

        extract($this->vars);
        include $cacheFile;
    }

    protected function compile($content)
    {
        $content = preg_replace('/\{\$(.*?)\}/', '<?php echo $1; ?>', $content);

        $content = preg_replace('/\{if (.*?)\}/', '<?php if($1): ?>', $content);
        $content = preg_replace('/\{else\}/', '<?php else: ?>', $content);
        $content = preg_replace('/\{\/if\}/', '<?php endif; ?>', $content);

        $content = preg_replace('/\{foreach (.*?)\}/', '<?php foreach($1): ?>', $content);
        $content = preg_replace('/\{\/foreach\}/', '<?php endforeach; ?>', $content);

        return $content;
    }
}


3️⃣ 使用

$tpl = new Template();

$tpl->assign('title', '测试页面');
$tpl->assign('age', 20);
$tpl->assign('list', ['苹果', '香蕉', '橙子']);

$tpl->render('view.html');


三、运行原理图

模板文件
   ↓
正则替换
   ↓
生成 PHP 文件
   ↓
include 执行
   ↓
输出 HTML

这就是:

Smarty
Blade
ThinkPHP 模板

的核心原理。


四、安全加强版(防 XSS)

上面的变量输出是不安全的:

<?php echo $name; ?>

应该改成:

<?php echo htmlspecialchars($name, ENT_QUOTES, 'UTF-8'); ?>

修改编译规则:

$content = preg_replace(
    '/\{\$(.*?)\}/',
    '<?php echo htmlspecialchars($1, ENT_QUOTES, "UTF-8"); ?>',
    $content
);


五、再进阶你可以加

功能做法
模板继承block 解析
include 子模板include 编译
layout 布局先解析内容块
缓存时间判断 filemtime
自定义函数注册函数表

六、如果你只是想要“最简单”

其实最简单就是:

extract($data);
include 'view.php';

直接在 view.php 里写:

<h1><?= $title ?></h1>

这就是:

PHP 本身就是模板引擎。


七、对比主流模板引擎

引擎特点
Smarty经典模板引擎
Twig安全严格
BladeLaravel 专用
原生自写最轻量

八、结论

如果是:

  • 小项目 → 原生 include 就够
  • 中型项目 → 自写编译型模板
  • 大项目 → 用成熟模板引擎

如果你愿意,我可以给你:

  • 🔥 100 行实现一个“类 Smarty”模板引擎
  • 🔥 支持模板继承的完整版
  • 🔥 带缓存优化的生产级模板
  • 🔥 MVC 框架最小实现(自写 PHP 框架)

你是想学习原理,还是想做一个可商用的轻量框架?