SharEDITor

教你成为全栈工程师(Full Stack Developer) 九-让模板文件帮你快速开发网页

全栈技术 教你成为全栈工程师(Full Stack Developer) 发表于 2016-04-21 16:45:17 阅读1896次


模板顾名思义是用来复制的样本,那么模板文件同样具有这样的特性:可继承、可重载、可嵌套,同时具备一些其他优点:流程控制、变量传递、链接自动生成等。html模板给我们开发带来怎样的好处呢?这一节我们继续改进我们的网站来说明模板的作用

请尊重原创,转载请注明来源网站www.shareditor.com以及原始链接地址

再做一张页面

 

新增/data/httpdir/mywebsite/app/Resources/views/blog/show.html.twig文件,内容如下:

 

<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
<!-- 上述3个meta标签*必须*放在最前面,任何其他内容都*必须*跟随其后! -->
<title>博客内容</title>

<!-- 新 Bootstrap 核心 CSS 文件 -->
<link rel="stylesheet" href="//cdn.bootcss.com/bootstrap/3.3.5/css/bootstrap.min.css">

<!-- 可选的Bootstrap主题文件(一般不用引入) -->
<link rel="stylesheet" href="//cdn.bootcss.com/bootstrap/3.3.5/css/bootstrap-theme.min.css">

<!-- jQuery文件。务必在bootstrap.min.js 之前引入 -->
<script src="//cdn.bootcss.com/jquery/1.11.3/jquery.min.js"></script>

<!-- 最新的 Bootstrap 核心 JavaScript 文件 -->
<script src="//cdn.bootcss.com/bootstrap/3.3.5/js/bootstrap.min.js"></script>

</head>
<body>

<div class="row bg-primary">
    <div class="col-sm-1 col-xs-1"></div>
    <div class="col-sm-11 col-xs-11"><h1><a href="" style="text-decoration: none;color: white;">MyWebSite</a></h1></div>
</div>

<div class="row jumbotron">
    <div class="col-md-1 col-xs-1"></div>
    <div class="col-md-10 col-xs-10"><h1>我的第一篇博客</h1></div>
    <div class="col-md-1 col-xs-1"></div>
</div>

</body>
</html>

在/data/httpdir/mywebsite/app/config/routing.yml中新增如下内容(注意缩进):

blog_show:
    path:     /blogshow/
    defaults: { _controller: AppBundle:Blog:show }

 

在/data/httpdir/mywebsite/src/AppBundle/Controller/BlogController.php的BlogController类中增加一个新方法,如下:

    public function showAction(Request $request)
    {
        return $this->render('blog/show.html.twig');
    }

 

这时打开http://172.16.142.130/app_dev.php/blogshow/可以看到一张新网页(注意:这里的172.16.142.130对应改成你虚拟机的ip)

 

那么这时候你会发现show.html.twig和list.html.twig除了<title>标签里的内容和body里的一个div内容不同之外完全一样,如果一个网站有成百上千张网页都大体相同,你会想到什么?对!把一样的部分包装成一个组件,使用它的网页把他include进来,但是html是一层一层标签的嵌套结构,include适合面向函数的语言。所以就产生了模板这种抽象方式。

 

模板抽象

 

我们修改app/Resources/views/base.html.twig文件内容如下:

 

<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
<!-- 上述3个meta标签*必须*放在最前面,任何其他内容都*必须*跟随其后! -->
<title>{% block title %}自定义标题{% endblock title %}</title>

<!-- 新 Bootstrap 核心 CSS 文件 -->
<link rel="stylesheet" href="//cdn.bootcss.com/bootstrap/3.3.5/css/bootstrap.min.css">

<!-- 可选的Bootstrap主题文件(一般不用引入) -->
<link rel="stylesheet" href="//cdn.bootcss.com/bootstrap/3.3.5/css/bootstrap-theme.min.css">

<!-- jQuery文件。务必在bootstrap.min.js 之前引入 -->
<script src="//cdn.bootcss.com/jquery/1.11.3/jquery.min.js"></script>

<!-- 最新的 Bootstrap 核心 JavaScript 文件 -->
<script src="//cdn.bootcss.com/bootstrap/3.3.5/js/bootstrap.min.js"></script>

</head>
<body>

<div class="row bg-primary">
    <div class="col-sm-1 col-xs-1"></div>
    <div class="col-sm-11 col-xs-11"><h1><a href="" style="text-decoration: none;color: white;">MyWebSite</a></h1></div>
</div>

{% block body %}
{% endblock body %}

</body>
</html>

 

可以看到这里面相比前面两个文件出现了这样两句:

<title>{% block title %}自定义标题{% endblock title %}</title>

{% block body %}
{% endblock body %}

 

这里的block就是可以重载的部分,那么我们现在可以修改list.html.twig了,改成如下:

{% extends "base.html.twig" %}

{% block title %}MyWebSite{% endblock title %}

{% block body %}
<div class="row jumbotron">
    <div class="col-md-1 col-xs-1"></div>
    <div class="col-md-10 col-xs-10"><h1>Welcome to MyWebSite!</h1></div>
    <div class="col-md-1 col-xs-1"></div>
</div>
{% endblock body %}

修改show.html.twig,改成如下:

{% extends "base.html.twig" %}

{% block title %}博客内容{% endblock title %}

{% block body %}
<div class="row jumbotron">
    <div class="col-md-1 col-xs-1"></div>
    <div class="col-md-10 col-xs-10"><h1>我的第一篇博客</h1></div>
    <div class="col-md-1 col-xs-1"></div>
</div>
{% endblock body %}

这时候在浏览器重新浏览http://172.16.142.130/app_dev.php/bloglist/http://172.16.142.130/app_dev.php/blogshow/效果是不是和之前一样,但是代码简单了许多

请尊重原创,转载请注明来源网站www.shareditor.com以及原始链接地址

 

变量传递

 

在MVC三个部分之controller里面我们调用render来渲染html的内容,那么你不禁会问:怎么把controller里的变量传递到html里来使用呢?下面我们来做个试验,修改src/AppBundle/Controller/BlogController.php文件,把

return $this->render('blog/show.html.twig');

改成

return $this->render('blog/show.html.twig', array('title' => '博客标题', 'content' => '博客内容'));

多传递一个php数组,数组里存了title和content

 

然后在show.html.twig中block body部分改成

<div class="row jumbotron">
    <div class="col-md-1 col-xs-1"></div>
    <div class="col-md-10 col-xs-10"><h1>{{ title }}</h1></div>
    <div class="col-md-1 col-xs-1"></div>
</div>
<div class="row">
    <div class="col-md-1 col-xs-1"></div>
    <div class="col-md-10 col-xs-10"><h4>{{ content }}</h4></div>
    <div class="col-md-1 col-xs-1"></div>
</div>

重新浏览http://172.16.142.130/app_dev.php/blogshow/看到我们在php代码里指定的title和content展示了出来

 

变量传递通过 {{ }} 这样的符号来传递

tips 1: 以刚刚传递的content变量为例,如果传递的content是一个array结构,加入里面有time、category、text等字段,那么,可以这样读取:{{ content['time'] }}

tips 2: 如果content是一个类结构的实例,这个类有time、category、text等属性(也就是有getTime()、getCategory()、getText()方法),那么可以这样读取:{{ content.time }}

tips 3: {{ }} 里还可以调用php原生方法,如:去掉 html标签方法{{ content | strip_tags }}、以原始html形式展示方法{{ content | raw }}

 

 

流程控制

 

有想过在html里面使用if else或者for循环吗?模板可以帮你,再次修改src/AppBundle/Controller/BlogController.php文件,把

return $this->render('blog/show.html.twig', array('title' => '博客标题', 'content' => '博客内容'));

改成

        $content = array();
        $content[] = array('category' => '类别1', 'text' => '内容1');
        $content[] = array('category' => '类别2', 'text' => '内容2');
        $content[] = array('category' => '类别1', 'text' => '内容3');
        $content[] = array('category' => '类别2', 'text' => '内容4');
        return $this->render('blog/show.html.twig', array('title' => '博客标题', 'content' => $content));

修改app/Resources/views/blog/show.html.twig,把第二组div改成:

{% for cont in content %}
{% if cont['category'] == '类别2' %}
<div class="row">
    <div class="col-md-1 col-xs-1"></div>
    <div class="col-md-10 col-xs-10"><h4>{{ cont['text'] }}</h4></div>
    <div class="col-md-1 col-xs-1"></div>
</div>
{% endif %}
{% endfor %}

 

浏览http://172.16.142.130/app_dev.php/blogshow/看到了什么效果?

 

传递过来的content是个数组,首先用{% for cont in content %}对content做了循环遍历,之后在循环体里用{% if cont['category'] == '类别2' %}做了逻辑判断,只展示类别为“类别2”的内容

 

链接生成

 

如果我们希望点击“内容”都能跳转到bloglist页面,怎么做呢?首先想到我们可以增加个超链接,像这样:

<a href='http://172.16.142.130/app_dev.php/bloglist/'>{{ cont['text'] }}</a>

但是这有一个问题:当网站发布时是不是还要改成

<a href='http://www.****.com/bloglist/'>{{ cont['text'] }}</a>

这是不够灵活的,所以模板为我们提供了链接生成的功能,还记得router.yml的内容吗?

app:
    resource: "@AppBundle/Controller/"
    type:     annotation

blog_list:
    path:     /bloglist/
    defaults: { _controller: AppBundle:Blog:list }

blog_show:
    path:     /blogshow/
    defaults: { _controller: AppBundle:Blog:show }

 

这里面的blog_list、blog_show这种名字开始起作用了,我们可以把“内容”改成如下:

<a href='{{ path('blog_list') }}'>{{ cont['text'] }}</a>

这样便可以自动根据实际环境生成blog_list对应的正确链接,amazing!

 

以上模板功能对于基本的网站开发足够了,如果想了解更多内容可以百度一下twig