在老项目里,我们通过 PHP 代码本身来创建视图模板文件,不过这种方式还有两个地方让人觉得还能有改进空间,一个是从代码复用的角度来看,HTML 的头尾很多代码都是相同的,但是我们都没有能复用上;另一个是,我们总是要使用 htmlspecialchars
函数来处理用户的数据,不仅很麻烦,而且还容易忘。
不过『模板引擎』已经把上面的两个问题解决了。『模板引擎』一般是指一种代码库,专门用来解决视图或者模板相关的问题。模板引擎库很多,Twig 是其中之一。因为 Symfony 默认安装了 Twig,我们就来看看如何使用 Twig 来创建页面。
我们先把前一章的 Task 控制器做一下修改:
<?php
namespace App\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Response;
// 设置控制器类继承 AbstractController,此父类提供很多有用的方法
class TaskController extends AbstractController
{
/**
* 前一章我们首页的方法名叫 indexAction,那是 Symfony 老版本的写法,
* 在新版里不再要求 Action 结尾,这里我们也沿用新版做法去掉 Action
*
* @Route("/", methods={"GET"})
*/
public function index()
{
// render 就是 AbstractController 提供的方法,会返回 Response 对象
return $this->render('task/index.html.twig', [
// 为了测试 twig 的转义功能,我们故意写一个 HTML 标签
'name' => '<script>',
]);
}
}
控制器里要『渲染(render)』的 task/index.html.twig
文件现在还不存在,我们需要先在 templates
目录创建它,并且写下以下的内容:
{# 这是 twig 的注释 #}
{# 这种写法相当于 PHP 里的 <?= $name ?> 或者 <?php echo $name ?> #}
{{ name }}
去掉注释,其实就是很简单的一句话,输出我们的 name
变量。我们现在来刷新首页,不出意外,我们能看到 <script>
,如果我们进一步观察,查看网页的源代码,我们会发现大于号和小于号都已经被转义了。
这就是 Twig 给我们带来的第一个好处,能帮我们『偷偷的』转义,这样文章开头提到的第二个问题自然就被解决了。实际上,Twig 模板会被 Twig 库读取后,『编译』成 PHP 文件,而在编译的过程当中,会自动加上转义函数来处理变量。
可能有人会问,假如我就不想自动转义怎么办?这个问题 Twig 也是有好几种做法的,你可以用 autoescape
标签来标记某个代码部分你不想开启自动转义功能,或者直接使用 raw
操作:
{% autoescape false %}
{{ name }}
{% endautoescape %}
{# 或者 #}
{{ name|raw }}
更多信息,大家可见 Twig 相关的文档,如果大家对 Twig 有兴趣也建议大家收藏官方文档网站。
我们再来看如何解决第二个问题。将模板文件做进一步修改:
{% extends 'base.html.twig' %}
{% block body %}
{{ name }}
{% endblock body %}
第一行代码告诉 Twig,此模板『继承(extends)』base.html.twig
模板,而这个模板实际上在我们安装完 Symfony 之后,就已经存在了。此模板的内容为:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>{% block title %}Welcome!{% endblock %}</title>
{% block stylesheets %}{% endblock %}
</head>
<body>
{% block body %}{% endblock %}
{% block javascripts %}{% endblock %}
</body>
</html>
看起来像是一个完整的 HTML 代码,但也夹杂了一些 Twig 代码。这些 Twig 代码定义了很多『块』,也就是 block,其实这依然利用了『抽象』的概念,即 base.html.twig
文件知道要生成 HTML5 的代码,而且知道有标题(title
块),有样式(stylesheets
块),有正文(body
块),有 JS 代码块(javascripts
块),但这些块具体是什么,它不管,感觉是不是跟我们之前说面向对象的时候的一些概念很像?其实不只是像,Twig 源代码编译成 PHP 文件之后,一个 Twig 模板文件就是对应一个 PHP 类,实际上 Twig 就是完全借鉴了类的概念。
子类可以继承父类,Twig 里也有子模板可以继承父模板,base.html.twig
就是我们的父模板,而我们自己创建的 task/index.html.twig
就是子模板,而父模板里定义的各个 block,就可以看成是类里的各个公开方法,子类可以重写父类的公开方法,这也是 task/index.html.twig
文件中 block body
那部分代码的意义。
另外,父类的方法可以提供一些默认的内容,比如父类里的 title
块,默认返回了 Welcome!
,这个时候刷新首页,你不仅依然能看到 <script>
,而且浏览器的标题栏也会变成 Welcome!
。
也许很多读者还会发现使用了父类之后,网页下方会多了一条有很多信息的条。这是 Symfony 框架在开发环境用来给开发者提供信息的 debug 条,我们以后会用到它,不过现在大家也可以把这个条点开,看看 Symfony 都为我们记录了什么有用的信息。
最后,有一个小技巧告诉大家。上一章有提到 bin/console
提供了很多有用的命令来让我们的开发更有效率,实际上我们除了自己创建控制器文件和模板文件,我们还可以通过下面的命令帮我们生成:
bin/console make:controller
回车运行后,会问你想要给控制器类起什么名字,这里假如我们写 TaskController
,再次回车确认,就会提示你已经生成好了 src/Controller/TaskController.php
文件和 templates/task/index.html.twig
文件了。虽然生成的文件我们要做进一步修改,但改文件肯定还是比从 0 开始创建文件要快多了。
本章节完整代码见这里。
人人都能看懂的全栈开发教程——模板引擎 by Chris Yue is licensed under a Creative Commons Attribution-NonCommercial-NoDerivatives 4.0 International License.

写作累,服务器还越来越贵
求分担,祝愿好人一生平安
天使打赏人