只要不是做后端接口开发和一些作为守护进程之类的服务器脚本,大多数时候都是在和浏览器打交道,因此合理组织并展现 html 标签是最为常见的工作。一般大家使用框架时,都会自带有一套视图组件和模板引擎。

我们不讨论这些组件和引擎的好坏。因为这些东西已经经过考验,可以在生产环境下使用。我们现在只是为了学习一些东西,这时候了解一些原理上的可能对以后的帮助更大,如果一些人真的很有时间,利用这些基础知识完全可以写一个自己的组件,即可当做练习,也可以拿去自用。

好了,说这么多,我还是希望很多人明白,视图和模板引擎实际上原理十分简单,所涉及的知识可以说是太基础不过的了。但,千万不要把视图和模板引擎搞混淆,这两个真的不是一个东西 。

为了理解这些,我们先从视图开始了解。

视图

视图,你所看见的部分。

<?php
echo 'hello, world';

从简单开始理解

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

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

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

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

文件 controller.php,代码如下

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

文件 view.php,代码如下

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>视图实例</title>
</head>
<body>
<p>时间戳 <?=$time?> 是 <?=$string?></p>
</body>
</html>

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

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

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

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

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

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

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

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

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

实战 —— 实现一个视图类

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

<?php
class View
{
protected $data = []; public function display($file)
{
extract($this->data); include $file;
} public function assign($key, $value)
{
$this->data[$key] = $value;
}
}

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

<!DOCTYPE html>
<html>
<head>
<title><?=$title?></title>
<meta charset="utf-8">
</head>
<body>
<h1><?=$title?></h1>
<p>
<?=$content?>
</p>
</body>
</html>

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

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

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

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

模板引擎

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

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

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

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

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


转:https://www.insp.top/article/use-php-to-achieve-view-component-and-template-engine

用 php 实现一个视图组件和模板引擎——基础的更多相关文章

  1. 写一个迷你版Smarty模板引擎,对认识模板引擎原理非常好(附代码)

    前些时间在看创智博客韩顺平的Smarty模板引擎教程,再结合自己跟李炎恢第二季开发中CMS系统写的tpl模板引擎.今天就写一个迷你版的Smarty引擎,虽然说我并没有深入分析过Smarty的源码,但是 ...

  2. SpringBoot 之 视图解析与模板引擎、 热部署、日志配置(四)

    个人博客网:https://wushaopei.github.io/    (你想要这里多有) 一 . SpringBoot环境下的视图解析技术 1. JSP JSP 是我们常用的视图技术了,但是Sp ...

  3. Laravel 5.2 三、中间件、视图与 Blade 模板引擎

    一.中间件 Laravel 的 HTTP 中间件提供了对路由的一层过滤和保护.下面模拟一下用中间件验证后台登录. 1. 创建中间件 cmd 窗口进入项目目录,使用 artisan 命令创建 php a ...

  4. Laravel之视图和Blade模板引擎

    一.视图 1.视图文件存放在resources/views目录2.视图载入及传参 return view('greeting', ['name' => 'James']); 还可以通过with ...

  5. 一个简单的PHP模板引擎

    PHP早期开发中通常是PHP代码和HTML代码混写,这也使代码中充斥着数据库操作,逻辑处理等.当项目不大时,这样的代码还可以接受,但是随着项目不断扩大,我们就会发现同一个文件中同时存在前端逻辑和后端处 ...

  6. thymeleaf模板引擎基础使用(转)

    刚好项目上用到这个模板引擎,记录以下基础用法. thymeleaf介绍 简单说, Thymeleaf是一个跟Velocity.FreeMarker类似的模板引擎,它可以完全替代JSP .相比其他的模板 ...

  7. smarty模板引擎基础(二)

    smarty模板引擎所需文件夹共可分为存放页面缓存的(cache).存放配置文件的(configs).存放模板扩充插件的(plugins).存放模板文件的(templates).存放编译后的模板文件的 ...

  8. 一个JavaScript组件都需要哪些基础api

    { init: function() { // 模块初始化,包括属性初始化和配置初始化及调用父类的初始化方法 } ,build: function() { // 模块构建,包括子模块构建,dom构建, ...

  9. thymeleaf模板引擎基础知识

    一.表达式 分为四类: 1.变量表达式 ${} :获取容器上下文变量的值. 举例: 获取application域中的username: ${application.username} 获取sessio ...

随机推荐

  1. [典型漏洞分享]一个典型的XSS盲打漏洞可导致全网用户cookie被盗取

    偶平时在做安全测试时,一般是以发现问题为主,点到为止,但做安全的同学可能也遇到过这样的问题,当你尝试向开发的同学描述一个漏洞危害怎么怎么样的时候,双方经常会有一种鸡同鸭讲的感觉,甚至他们觉得我们在夸大 ...

  2. hive删除列

    hive中删除列时没有与mysql语句alter table <table> drop column <col>对应的语句. 然而依然可以完成此功能:使用ALTER TABLE ...

  3. jquery中remove()与detach()的区别

    说到删除节点,马上就会想到remove,不过原来还有一个detach,而且它们还是有区别的,就是detach保留了jquery的数据,而remove就会完全删除干净.所以如果在删除一个dom节点后还想 ...

  4. lua调试的工具选择

    近期看到一个关于vs的lua调试插件, 装了vs2012试了下, 忍不住发此文总结下lua各种调试工具 Decoda 这是现今地球上调试lua5.1最方便的工具, 没有之中的一个. 强大的注入式调试, ...

  5. iOS:第三方框架MJPhotoBrowser图片浏览器的使用

    介绍:MJPhotoBrowser这个第三方库是MJ老师封装的一套用来浏览图片的浏览器,可是是本地图片.网络图片.gif图片等,其也依赖了SDWebImage.SVProgressHUD.YLGIFI ...

  6. iOS:UIResponser控件的介绍(响应者)

    UIResponser响应者控件   知识: 在iOS中不是任何对象都能处理事件,只有继承了UIResponser的对象才能接收并处理事件.我们称之为“响应者对象” UIApplication,UIV ...

  7. OSG立体模式下动态修改相机远近裁剪面的实现

    1. 非立体模式下动态修改相机远近裁剪面 class GLB_DLLCLASS_EXPORT CGlbGlobeClipHandler : public osg::NodeCallback    { ...

  8. ISP图像调试工程师——对比度增强(熟悉图像预处理和后处理技术)

    经典对比度增强算法: http://blog.csdn.net/ebowtang/article/details/38236441

  9. 将思维转向rss

    本屌丝因为穷住在了离市区比较远的农民房,平时上下班单程地铁时间接近一小时.在这漫长的一小时里,总得干点什么来蹉跎这段时光,看手机是最容易实现的事情.最地铁信号不好,手机也没什么好看的. 经过高人指点说 ...

  10. Microsoft.Office.Workflow.Actions Namespace

    Microsoft.Office.Workflow.Actions Namespace SharePoint 2010   Contains the workflow activities that ...