让模板文件帮你快速开发网页

优质
小牛编辑
144浏览
2023-12-01

再做一张页面

新增/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="">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="">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/效果是不是和之前一样,但是代码简单了许多

变量传递

在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