视图

视图,你所看见的部分。

  1. <?php
  2. echo 'hello, world';

从简单开始理解

这就是个视图文件中的代码,没错就这么简单。视图,实际上是在 MVC 这种架构上提出的。MVC 中,视图负责呈现数据。因此可以说只要是输出了数据的,都叫做视图。

在没有使用框架的时候,业务逻辑、数据的读写、组织和展示都是在一堆代码里,难以剥离,随着项目增大变得越来越难以维护。MVC 有效的分离了三者,各司其职。视图作为呈现数据的,只负责组织、展示,不再负责读写和业务逻辑。

既然视图只负责呈现数据,那么单独成一个文件,这个文件内的代码绝对不要读取数据库、做业务判断,那么就算你将视图独立出来了。这时候大多数人会想到,视图中的数据从哪来呢?

我们以一个简单的例子实现一个业务逻辑和视图分离的结构。

文件 controller.php,代码如下

  1. <?php
  2. $time = time();
  3. $string = ($time % 2) == 0 ? '偶数' : '奇数';
  4. // 加载视图
  5. include 'view.php';

文件 view.php,代码如下

  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <meta charset="utf-8">
  5. <title>视图实例</title>
  6. </head>
  7. <body>
  8. <p>时间戳 <?=$time?> 是 <?=$string?></p>
  9. </body>
  10. </html>

代码写好,运行后结果是预期的,对吗?

这两个文件中,毋庸置疑 view.php 就是视图文件,而 controller.php 你可以当做一个控制器,因为它实现了主要的业务逻辑(虽然极其简单)。尽管简洁,但在结构上我们已经完全分离。

事实上,目前所有的框架的视图的实现都大致如此,没什么特别的、神秘的地方,只是说框架它做了更多的事,比如验证视图文件的合法性、通过更少的参数去加载视图等等。

如何传递一个变量到视图文件?

我相信很多人在这个上面有着很多的疑惑。比如我们常看到这样向视图传递变量:

  1. // laravel 通过视图类的 with 方法传递
  2. View::make('view')->with('value', '实际的数据');
  3. // Smarty 模板引擎通过 assign 方法向最终的编译好的视图传递变量
  4. $smarty->assign('value', '实际的数据');
  5. // ...

实际上,在上面的逻辑与视图分离的例子中已经说了。当 include 或 require 一个文件时,该文件会继承引入他的那段代码的作用域。php 官方文档是这么说的:

当一个文件被包含时,其中所包含的代码继承了 include 所在行的变量范围。从该处开始,调用文件在该行处可用的任何变量在被调用的文件中也都可用。不过所有在包含文件中定义的函数和类都具有全局作用域。

如果 include 出现于调用文件中的一个函数里,则被调用的文件中所包含的所有代码将表现得如同它们是在该函数内部定义的一样。所以它将遵循该函数的变量范围。此规则的一个例外是魔术常量,它们是在发生包含之前就已被解析器处理的。

实战 —— 实现一个视图类

假设我们有一个视图类,定义在文件 View.php

  1. <?php
  2. class View
  3. {
  4. protected $data = [];
  5. public function display($file)
  6. {
  7. extract($this->data);
  8. include $file;
  9. }
  10. public function assign($key, $value)
  11. {
  12. $this->data[$key] = $value;
  13. }
  14. }

我们现在有模板文件,定义在文件 Template.php:

  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <title><?=$title?></title>
  5. <meta charset="utf-8">
  6. </head>
  7. <body>
  8. <h1><?=$title?></h1>
  9. <p>
  10. <?=$content?>
  11. </p>
  12. </body>
  13. </html>

然后我们的主要业务逻辑代码如下:

  1. <?php
  2. // 包含视图类文件
  3. include 'View.php';
  4. $view = new View();
  5. $view->assign('title', '视图测试');
  6. $view->assign('content', '这是一个视图类的示例');
  7. $view->display('Template.php');

输出的内容大家都已经看得出来了,我就不截图了。

至此,大家应该都明白如何实现一个视图了吧?其实原理就这么简单。

模板引擎

模板引擎的诞生实际上是将视图拆分出来以后的事儿。大家看到了,上面例子中,所有模板中的变量,都是通过原生的 php 语法进行输出。假如单纯是输出内容,其实不用模板引擎也可以,但是一旦涉及到需要复用模板或者对视图文件进行模块化的拆分,实现诸如继承、布局之类的功能时,原生的 php 语法似乎需要写更为复杂的代码才能实现。

很显然,我们不应该在视图文件内写超出职责或过于繁杂的额外代码,因此,模板引擎就显得十分必要。

模板引擎的用处并不是所谓的方便前端的美工和网页设计师,因为原生的语法比很多模板引擎语法更为简洁。实际上,模板引擎最主要的任务是简化在视图上的额外代码,比如处理布局、模板继承等等。

说了那么多,如何实现模板引擎?

其实模板引擎就是将一个指定的模板标记通过正则匹配,替换成相应的合法 php 语句而已。

php实现简单视图模板(视图引擎)的更多相关文章

  1. ASP.NET WEB应用程序(.network4.5)MVC Razor视图引擎2 视图模板页

    https://www.cnblogs.com/xlhblogs/archive/2013/06/09/3129449.html MVC Razor模板引擎 @RenderBody.@RenderPa ...

  2. AspNet MVC与T4,我定制的视图模板

    一. 遇到的问题 文章开头部分想先说一下自己的困惑,在用AspNet MVC时,完成Action的编写,然后添加一个视图,这个时候弹出一个添加视图的选项窗口,如下: 很熟悉吧,继续上面说的,我添加一个 ...

  3. Solon Web 开发,七、视图模板与Mvc注解

    Solon Web 开发 一.开始 二.开发知识准备 三.打包与运行 四.请求上下文 五.数据访问.事务与缓存应用 六.过滤器.处理.拦截器 七.视图模板与Mvc注解 八.校验.及定制与扩展 九.跨域 ...

  4. laravel4通过控制视图模板路劲来动态切换主题

    通过控制视图模板路劲来动态切换主题 App::before(function($request) { $paths = Terminal::isMobile() ? array(__dir__.'/v ...

  5. vs 2013下自定义ASP.net MVC 5/Web API 2 模板(T4 视图模板/控制器模板)

    vs 2013下自定义ASP.net MVC 5/Web API 2  模板(T4 视图模板/控制器模板): Customizing ASP.NET MVC 5/Web API 2 Scaffoldi ...

  6. ThinkPHP框架视图详细介绍 View 视图--模板(九)

    原文:ThinkPHP框架视图详细介绍 View 视图--模板(九) 视图也是ThinkPHP使用的核心部分: 一.模板的使用 a.规则 模板文件夹下[TPL]/[分组文件夹/][模板主题文件夹/]和 ...

  7. PHP Lavavel 使用控制器 传递变量 以及调用 视图模板

    控制器第一次入门使用 位置: 在app/Http/Controllers 目录下创建文件名格式:例如 UserController路由调用格式:Route::get('user/tom','UserC ...

  8. 【SQL模板】二.创建表视图模板TSQL

    ---Name: 创建表视图模板.sql ---Purpose: 用于创建 数据库中 新的数据表/视图 ---Author: xx ---Time: 2015-12-18 10:26:06 ---Re ...

  9. Xamarin XAML语言教程模板视图TemplatedView(二)

    Xamarin XAML语言教程模板视图TemplatedView(二) (2)打开MainPage.xaml文件,编写代码,将构建的控件模板应用于中TemplatedView.代码如下: <? ...

随机推荐

  1. EffectiveJava读书笔记

    less, but is more. 创建和销毁对象 避免创建不必要对象 消除过期的对象引用 使可变性最小 泛型 用标记接口定义类型 检查参数有效性 返回零长度的数组或集合,而不是null 需要精确答 ...

  2. Jmeter4.0启动闪退问题解决方案

    jmeter:4.0 jdk版本:1.8 在Jmeter.bat的最后添加pause可以让Jmeter启动停止: 添加了pause进行强制停止在启动命令页面,查看到Jmeter报错信息如下: 第一次解 ...

  3. ios的概述和了解的个人总结

    ios的概述: ios  为apple手持设备系统: OS X 为apple的macbook.imac.mac min等的操作系统: 应用程序的格式:dmg    pkg   app iphone 第 ...

  4. HCharts的y轴保留一位和 两位小数

    保留一位小数,有一位小数的不变 yAxis : { labels : {  formatter : function () { var strVal = ''+this.value ; if (str ...

  5. spring boot jar 进程自动停止,自动终止,不能后台持续运行

    第一次部署spring boot 到linux上,用命令java -jar **.jar,发现应用自动退出,进程停止了.后来发现要不挂断的执行命令,忽略所有的挂断信号,用以下命令解决 nohup ja ...

  6. String、ANSIString、PChar及TBytes之间的转换 BytesOf move stringof

    一.string转为ansistring 1.直接赋值 (有警告)2.ansistring()类型强制转换.(无警告) 二.ansistring 转为string 1.直接赋值 (有警告)2.stri ...

  7. Spring MVC 基础篇4

    Spring MVC Controller中返回数据到页面 1.使用ModelAndView 进行数据返回到请求页面 2.利用Map类型的入参进行Controller返回到页面上 3.将数据放到Ses ...

  8. hdu 1054(最小点覆盖集)

    Strategic Game Time Limit: 20000/10000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) ...

  9. 使用Derby ij客户端工具

    Derby是开源的.嵌入式的Java数据库程序,ij是Derby提供的客户端工具,相当于其他数据库提供的sqlplus工具. ij是纯Java的程序,不用安装,使用起来就像运行普通的Java应用程序一 ...

  10. STL模板整理 pair

    pair pair是一种模板类型,其中包含两个数据值,两个数据的类型可以不同.如果一个函数有两个返回值的话,如果是相同类型,就可以用数组返回,如果是不同类型,就可以自己写个struct ,但为了方便就 ...