开始之前
最近因为项目需求,搞了个模板引擎。github地址:https://github.com/shooke/template
过去写的一些小东西,和一些允许开源的项目都放到了gitee上,但是实在事太多了,于是把一些小东西开始往github上转。以后github上一些通用的开源的东东,gitee上就只放项目相关的。
缘由
为什么要开发个模板引擎呢,现在有这么多的模板引擎,比如元老级的smarty,Laravel中使用的Blade,还有大名鼎鼎的Twig。这么多还不够用吗?
不够,不行。
我需要一个简单易用便于理解的模板引擎,5分钟内就可以使用。这是最最最最最重要的。smarty首先被踢掉。
然后是blade,这个仁者见仁智者见智,都说优雅,但是我觉得还不够优雅,语法的使用太方言了(因为Laravel号称自己是优雅的语义化的,所以不好意思说他不语义,只能说他的语义化,很别扭。估计要被不少L粉喷了,不过没关系,现在Laravel有点风气不正,只要有人提出质疑,就会有无数的水军来说你不懂之类的)。
还有大名鼎鼎的twig,据说这是Symfony和Drupal用的模板引擎,这两位老大哥恐怕无人不知吧。
认识blade和twig
首先说一下twig,他的使用语法我比较喜欢,很容易看懂,简单易学。
基本语法
{% for user in users %}
* {{ user.name }}
{% else %}
No users have been found.
{% endfor %}
指定布局文件
{% extends "layout.html" %}
定义展示块
{% block content %}
Content of the page...
{% endblock %}
很简单吧,而且结尾和开头都是对称的。
再看看blade
<!-- 文件保存于 resources/views/layouts/app.blade.php -->
<html>
<head>
<title>应用程序名称 - @yield('title')</title>
</head>
<body>
@section('sidebar')
这是 master 的侧边栏。
@show
<div class="container">
@yield('content')
</div>
</body>
</html>
<!-- Stored in resources/views/child.blade.php -->
@extends('layouts.app')
@section('title', 'Page Title')
@section('sidebar')
@parent
<p>This is appended to the master sidebar.</p>
@endsection
@section('content')
<p>This is my body content.</p>
@endsection
看到这写五花把门的语法我就已经凌乱的,一万只草泥马崩腾而过啊,这是草泥马家乡的语义吗,这方言我感到务必凌乱。看到上面的代码你知道@yield是什么吗,去看文档吧。但是你要忍住,还有各种五花八门的语法让你凌乱,难道只要写出一手让别人难以理解的规则才能展示自身的强大?我都怀疑laravel的作者是不是脑子里太乱了。
好吧我承认不喜欢blade。但是我承认他是很强大的,展示块的定义,内容继承,他都有。看到哪个parent了吗那就是继承布局中的内容。这是个很实用的功能。
成果
看到上面两个强大的模板引擎,我们来总结一下他们的功能
- 数据块block/section 这是一个很强大的功能,可以灵活的控制每一个展示块
- 继承机制parent 使用parent继承调用布局中的内容块
- 多文件组合include 利用include可以将多个模板组合到一起,实现多种不同场景下的代码复用
- 灵活的变量函数以及常量使用
- 优雅的标签逻辑控制 你可以充分利用ide软件的代码提示和自动完成功能,而不需要安装特殊插件
- 模板自动监听 当模板更新时,刷新页面,模板引擎会自动进行编译,展示最新内容
好吧后面两条是我加上的,也是我希望的,虽然blade不具备,但是这不正是我要客服的吗。
于是一个小小的模板引擎就诞生了,它具备上面写的所有功能特点。来看看他的风采吧。
<!--布局文件的代码-->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title><block title>默认标题</block></title>
</head>
<body>
<!--展示块定义-->
<block content>我是布局模板content</block>
<!--引入模板-->
<include footer></include>
</body>
</html>
<!--内容模板-->
<!--展示块定义,会覆盖布局中的站位-->
<block title>{{ $title }}</block>
<block content>
我是内容模板,但是我用parent标签,调用了布局文件中content的内容<br>
<parent content></parent>
</block>
是不是清爽至极。使用html标签的方式进行代码书写,可以在所有ide软件中实现代码不全。上面的代码实现了展示块定义,内容模板展示块覆盖布局模板,以及继承和,外部引入include。
当然,除了对模板的总体管理,模板中还要有流程控制和变量输出,语法同样简单的令人发指
//变量
{{ $title }}
// 函数
{{ date('Y-m-d') }}
//普通常量跟变量用法一致,需要用{{}}括起来
{{ CONST_VAR }}
//两边下划线的常量直接使用
//会翻译为< ?php if(defined('__APP__')){echo __APP__;}else{echo '__APP__';} ?>
__APP__
// 三目运算
{{ $a==0 ? 0 : 1 }}
if判断
<if ($var>1)>
$var>1
<elseif ($var==1)>
$var=1
<else/>
$var<1
</if>
for循环
<for ($i=0;$i<5;$i++)>
{{ $i }}
</for>
普通当然for循环
for in
<for $item in $array>
{{ $item['title'] }}
</for>
相当于foreach($array as $item)
<for ($item,$index) in $array>
{{ $index }}=>{{ $item['title'] }}
</for>
相当于foreach($array as $index=>$item)
foreach 跟源生php写法对应只是换成了php标签形式
<foreach ($array as $item)>
{{ $item['title'] }}
</foreach>
<foreach ($array as $index=>$item)>
{{ $index }}=>{{ $item['title'] }}
</foreach>
是不是很简单。你都很难想像,为什么那些大框架的牛人就没有使用这种简单的语法。
再看看程序中如何使用
php中初始化
include "../Template.php";
$view = new Template();
$view->templatePath = './template/';// 模板路径 最后以/结尾
$view->compilePath = './compile/';// 编译文件存放路径 最后以/结尾
$view->layout = 'layout';// 布局文件在末班目录下,如果不适用可以定义成空字符串或false
// 渲染模板
$view->render('index',[
'title'=>'测试页',
'content'=>'内容',
'array'=>[
1,2,3
]
]);
//清空缓存
//$view->clean();
就是这么简单,喜欢可以去github下载下来使用https://github.com/shooke/template