MVC思想

代码发展历程

定义:代码发展历程其实也是随着软件工程思想的成熟,并依赖硬件水平的提高而形成的自然过渡。在过渡过程中主要形成了以下几种开发方式。

  1. 混编模式:即PHP代码与HTML是互相嵌入的
  • 优点:服务器解析效率最高
  • 缺点:代码复用性极低、视觉效果差、可维护性差
  1. 模板技术:将PHP代码与HTML代码进行分离,PHP中实现业务逻辑和数据处理,HTML中只进行数据的显示
  • 优点:代码复用性增强、视觉效果增强、前后端分离有助于前后端开发工程师维护
  • 缺点:小项目开发效率降低、服务器解析效率降低
  1. MVC思想:在模板技术之上,将PHP代码的业务逻辑处理部分和数据操作部分继续分离,独立维护
  • 优点:分类好管理、视觉效果好、维护性强
  • 缺点:前期开发效率低、服务器解析效率最低
  1. 发展历程
  • 混编模式是PHP早期设计的模式,当时要完成的内容很简单(个人博客),硬件效率也不是那么高(网络传输效率不高)
  • PHP逐渐被开发人员所喜爱,开始进行一些较大项目,为了方便维护,就进行了前后台分离,出现了模板技术
  • 面向对象开发作为编程主流,PHP也朝着这个方向发展,作为大型项目的支撑,需要有更好的代码结构,实现代码的复用和后续维护,因此出现了MVC思想

总结

  1. PHP随着时代的发展,经历了三个阶段:混编阶段、模板技术(前后端分离)和MVC思想设计
  2. 每个阶段都有彼此的优缺点
  3. MVC思想符合人类思维模式,缺点是服务器解析成本高,不过随着硬件的发展和网络的发展,这些效率相对开发维护而言,已经不足考虑

MVC思想介绍

定义:MVC思想,并非一种特定的技术,而是一种基于面向对象思想形成的有利于代码复用的设计行为。基于MVC思想开发的代码更加符合人类行为特性,也更利于后期项目维护和扩展。

  1. MVC是一种缩写结构
  • M:Model,模型,专门负责数据操作,针对数据库部分的代码。一个模型(类)针对一张数据表
  • V:View,视图,专门负责结果数据渲染(HTML+CSS+Javascript)。
  • C:Controller,控制器,负责所有的业务处理。一个控制器控制(类)一类业务
  1. MVC思想设计下的代码工作逻辑
  • 用户发起请求:请求控制器C
  • 控制器处理业务逻辑
    • 遇到数据处理需求:请求模型M实现数据库操作
    • 处理结果展示:调用视图V显示渲染数据
浏览器->服务器: 发送请求 服务器->控制器: 控制器接收请求 note right of 控制器:控制器接收请求\n业务处理 控制器-->模型:数据处理需求 note right of 模型:数据库操作 模型-->控制器:返回数据 控制器-->视图:数据渲染处理 note right of 视图:渲染数据 视图-->控制器:返回渲染结果 控制器->服务器:控制器处理完毕\n交给服务器 服务器->浏览器:服务器返回执行结果 note left of 浏览器:解析渲染后\n的数据结果
  1. 在面向对象的MVC中,因为模型是针对具体数据表,意味着每个模型都需要进行数据库的连接操作,这个时候通常会设计一层专门负责数据库初始化部分的(类似二次封装PDO,没有具体数据业务,只负责数据库底层操作),我们把这层叫做DAO(Data Access Object)数据访问对象

总结

  1. MVC并非一种技术,而是一种代码分离设计的思想
  2. MVC会让代码运行变慢,但是基于现在硬件性能,这个效率影响一般可以忽略
  3. MVC是由控制器、模型、视图三部分组成
  • 控制器:负责所有事务处理,也包括调用模型和视图
  • 模型:只负责数据逻辑处理,包括操作数据库
  • 视图:只负责数据渲染,主要是HTML+CSS+Javascript
  1. 通常情况下,面向对象中还会在模型和数据库之间增加一层DAO来专门负责数据库底层实现

MVC代码设计

定义:MVC代码设计,就是当一个系统要实现时,我们如何区分哪里该由控制器处理,哪里该由模型处理,最后如何在视图中渲染。

  1. 区分业务设计控制器:根据业务相关性和相似性,将对应业务划分到一起,由一个控制器来实现,控制器设计成类,不同方法代表不同业务处理,如后台的注册、登录以及注销这块,都属于权限功能,可以划分到一起;控制器可以区分前后台(看系统需求是否需要区分),可以增加相应的命名空间;为了后期代码好维护,可以增加控制器后缀controller
  1. //后台权限控制器
  2. //命名空间
  3. namespace admin\controller; //表明是后台代码,而且是控制器
  4. class PrivilegeController{
  5. //一个方法实现一个小业务:一次请求完成用户一次需求
  6. public function login(){
  7. //可以是单独的获取登录表单,也可以在里面使用判定方式实现获取表单和完成登录两个功能
  8. if(isset($_POST['username'])){
  9. //用户有提交用户名:说明当前是要完成登录功能
  10. //代码实现登录功能:调用模型
  11. }else{
  12. //没有提交表单:说明是用来获取登录表单
  13. //加载登录视图(HTML)
  14. }
  15. }
  16. //注册功能
  17. public function register(){
  18. //实现注册功能(注册和加载注册表单)
  19. }
  20. }
  1. 区分数据增加模型:模型的设计通常是基于表的,即一张表会有一个对应的模型类,对应表的所有操作(增删改查)都会有当前模型类来实现,所有的SQL指令都是封装到当前模型中。与控制器一样,也应该增加相应的 命名空间,以及模型后缀model
  1. //后台管理员模型
  2. namespace admin\model;
  3. class AdminModel{
  4. //模型针对表,所以通常会在模型中增加一个表名:因为所有方法都会涉及到SQL,便于以后维护
  5. protected $table = 'admin';
  6. //根据用户名获取用户信息
  7. public function getUserinfoByUsername($username){
  8. //组织SQL
  9. $sql = "select * from {$this->table} where username = '{$username}'";
  10. //执行:通常调用DAO执行即可
  11. //返回数据执行结果
  12. return $res;
  13. }
  14. //获取所有用户信息
  15. public function getAll(){
  16. $sql = "select * from {$this->table}";
  17. //调用DAO执行SQL并返回结果
  18. return $users;
  19. }
  20. }
  1. 选择合适视图:视图通常是前端提供好,后端人员要做的就是如何去在视图中增加对应的PHP输出指令,将数据放到合适的位置:假设当前获取的是用户的登录信息
  1. <html>
  2. <header></header>
  3. <body>
  4. <table>
  5. <tr><td>序号</td><td>用户名</td><td></td>上次登录时间</td></tr>
  6. <?php foreach($logininfo as $k => $info):?>
  7. <tr>
  8. <td><?php echo $k+1;?></td>
  9. <td><?php echo $info['username'];?></td>
  10. <td><?php echo $info['login_time'];?></td>
  11. </tr>
  12. <?php endforeach;?>
  13. </table>
  14. </body>
  15. </html>
  1. 在实际开发项目中,会有很多控制器,每个控制器本质要做的事情都差不多,只是具体的业务逻辑不一样。此时就会出现很多类似的功能,如操作成功、失败、页面找不到等等,此时如果在所有控制器中都去写对应的方法,那么肯定是有资源浪费的,此时就可以从这些控制器中抽离一部分公共代码出来,形成父类,从而实现代码的复用
  1. //父类控制器:通常在核心中
  2. namespace core;
  3. class Controller{
  4. //公共代码
  5. public function __construct(){
  6. //控制器的初始化操作
  7. }
  8. protected function success(){
  9. //成功操作
  10. }
  11. protected function error(){
  12. //失败操作
  13. }
  14. //......
  15. }
  1. //子类控制器继承父类控制器
  2. namespace admin\controller;
  3. use \Core\Controller; //引入父类
  4. class IndexController extends Controller{
  5. //业务方法
  6. public function index(){
  7. //调用父类公共方法
  8. $this->success();
  9. }
  10. }
  1. 同样的,模型是针对一张表一个模型,而每个模型都需要利用DAO来实现数据库的底层操作,以二次封装的PDO为例,所有的模型类都需要在构造方法中实现PDO的实例化,而且还会有很多公共的功能,如查询全部、通过ID进行查询等常用方法,此时也可以将模型的公共部分抽离出来,形成父类,而其他模型类只需要继承该类即可
  1. //父类公共模型
  2. namespace core;
  3. class Model{
  4. //实现DAO的初始化:通常使用构造方法,因为所有模型子类继承该类都会先调用构造方法
  5. public function __construct(){
  6. //实现DAO类的初始化,完成数据库初始化操作:通常是用对象保存得到的DAO对象
  7. $this->dao = new DAO(); //假定操作
  8. }
  9. //获取所有数据
  10. public function getAll(){
  11. $sql = "select * from {$this->table}"; //子类模型中有受保护的属性$table,父类也可以调用(最终是子类调用该方法)
  12. //执行完成,返回结果即可
  13. return $rows;
  14. }
  15. }
  1. //子类模型继承父类
  2. namespace admin\model;
  3. use \Core\Model;
  4. class UserModel extends Model{
  5. //表名属性
  6. protected $table = 'user';
  7. }
  8. //当前类没有自己的构造方法,意味着实例化UserModel的时候会调用继承自Model类的构造方法,从而实现DAO的实例化,也就是说实例化的UserModel对象,可以直接调用父类的getAll方法来实现数据库的操作

总结

  1. MVC思想的指导思路
  • 区分业务:确定是共用还是单独创建控制器
  • 区分数据:确定是属于控制器还是应该创建模型
  1. MVC思想中,会存在很多重复的内容,此时就需要我们进行抽象化
  • 公共控制器代码:父类控制器
  • 公共模型代码:父类模型

项目单一入口

定义:单一入口,是指一类业务会统一请求一个对应的控制器,所有的请求都是由控制器来处理;项目单一入口是指,所有的请求都只请求一个入口文件,其他的所有代码的调用执行,都是由该入口文件来管理。

  1. 项目单一入口是指在基于MVC设计情况下,在进入MVC之前,由一个统一的入口文件来进行管理,所有的用户(浏览器)请求都只允许访问入口文件
浏览器->服务器:发起请求 服务器->入口文件\nindex.php:统一由入口文件处理\n通常是index.php note right of 入口文件\nindex.php:入口文件开始\n分发控制器 入口文件\nindex.php-->控制器: 控制器-->模型:调用 note right of 模型:完成数据库操作 模型-->控制器:返回数据 控制器-->视图:加载 note right of 视图:完成数据渲染 视图-->控制器:返回渲染数据 控制器-->入口文件\nindex.php:返回MVC处理结果 入口文件\nindex.php->服务器:PHP处理结果交给服务器 服务器->浏览器:服务器返回执行结果 note left of 浏览器:浏览器\n完成解析
  1. 在真实项目单一入口中,入口文件通常会很简单,为了入口的可操作性,会将不同的内容分散到不同的文件中。一个简单的项目单一入口文件,也会将入口文件中的初始化部分,分离到另外一个文件中(初始化类)
  • 入口文件index.php:加载初始化类,激活初始化类
  • 初始化类:实现各类初始化(路径常量、系统设置、配置文件加载、路由功能、自动加载、控制器分发)

总结

  1. 单一入口是基于MVC思想的直接实现,用户的请求就是根据业务不同请求不同控制器
  2. 项目单一入口是指用户所有的请求都是请求一个PHP入口文件,其他的事情都是PHP内部处理
  3. 项目单一入口能够很好的保护系统内部的文件结构安全
  4. 项目单一入口会增加前期开发难度,但是在开发后期就会轻松(基础部分只需要开发一次)

    Smarty模板技术

    思考:为了代码能够更好的维护,我们会将PHP代码尽量从HTML中分离出来,但是不可避免的还是要在HTML中写入很多数据,这个时候依然需要用到很多PHP标签之类的,有没有更好的方式呢?

引入:PHP理论上要把数据通过HTML进行渲染,所以无论如何都是会出现嵌套的,但是我们可以有更好的方式,让PHP标签不出现在HTML中,从而让HTML中的代码看上去更整洁,这个技术就是模板技术。模板技术有很多,但是技术比较早,也比较全面的是Smarty模板技术(ThinkPHP3框架以后也自带模板引擎)。

  • 模板技术原理
  • Smarty学习

总结

  1. 模板技术在Web编程中使用非常广泛,能够让前端界面变得非常简洁
  2. Smarty模板技术功能强大,使用起来却非常方便

模板技术

思考:PHP之所以能够写在HTML中,一是因为PHP本身有标签能够区分其他代码,二是因为服务器能够把各种类型的代码文件交给PHP引擎处理。如果我们在HTML中不使用PHP标签能否将PHP要展示的数据显示出来呢?

引入:HTML文档实际上可以看成是一个字符串文件,那么也就可以将文档内容读入到PHP里面。因此,除了在HTML中直接写对应的PHP标签代码可以解析,我们也可以让PHP去尝试以其他的方式来实现数据在HTML里的插入,这个就得用到替换。

模板技术原理

定义:模板技术,即利用特定的占位符放到一个文档中的某个部位,然后利用相应的方式找到对应的占位符,并将数据实现占位符替换。

  1. 原来要在HTML中显示数据的方式:在PHP文件中准备好数据,然后在HTML中写一个echo指令,利用PHP文件包含HTML文件即可
  1. //PHP文件,获取数据,然后加载HTML文档
  2. $var = 'hello world';
  3. //包含HTML文件
  4. include_once 'hello.html';
  1. <--!hello.html-->
  2. <html>
  3. <header></header>
  4. <body>
  5. <?php echo $var;?>
  6. </body>
  7. </html>
  1. 以上方式会让HTML中嵌入很多PHP标签,从而影响文档的整体性,此时我们可以换一种思路

在HTML中要显示的数据使用一个类似HTML的标记,而并非PHP输出语句

  1. <!--hello.html-->
  2. <html>
  3. <header></header>
  4. <body>
  5. {$hello}
  6. </body>
  7. </html>

在PHP中也不再进行文件的加载,而是才有读取的形式

  1. $hello = 'hello world';
  2. //读取文件
  3. $str = file_get_contents('hello.html');

如果此时输出$str,那么得到的就是hello.html直接访问的结果。如果想要在{hello}处显示相应的数据,那么就需要进行占位符替换

  1. $hello = 'hello world';
  2. //读取文件
  3. $str = file_get_contents('hello.html');
  4. //对$str中的{hello}进行替换,替换成$hello中的数据
  5. $str = str_replace('{$hello}',$hello,$str);
  6. //输出替换后的结果
  7. echo $str;
  1. 以上就是一种直接替换成成品的模板技术原理,但是实际上模板技术是要为项目服务的,以上方式虽然能解决问题,但是太过简单。比如说一个数组传入,以上方式就不合适了,所以真正的模板技术算法是比较复杂的。而且考虑到项目的效率,通常模板技术会经历以下几层方式
  • 编译:对原始的PHP文件提供的内容,和HTML提供的模板进行编译,编译的结果就是形成一个可执行的PHP编译文件
  1. <!--原模板文件-->
  2. <html>
  3. <header></header>
  4. <body>
  5. {$hello}
  6. </body>
  7. </html>
  1. <!--编译后的文件-->
  2. <html>
  3. <header></header>
  4. <body>
  5. <?php echo $hello;?>
  6. </body>
  7. </html>
  • 执行:编译后的文件就已经可以直接被PHP引擎解释执行了
  1. $hello = 'hello world';
  2. //包含文件
  3. include '模板技术编译后的PHP文件'

总结

  1. 模板技术原理的本质是在HTML中设置相对简洁的标签,然后利用PHP实现内容的替换(这个过程由程序实现,开发人员不需要管理,只需要在需要显示数据的位置使用特定的标签即可)
  2. 模板技术是需要考虑项目实现和效率的,所以通常会产生中间产物(编译文件)来提升效率(后期不用再进行编译了)

Smarty模板技术

思考:模板技术能够让开发人员专注后台数据提供,而前端人员也不用因为PHP代码的各种存在而显得代码很混乱。但是如果要自己实现的话,应该要提供很多代码逻辑吧?

引入:小项目的话其实不用模板引擎也可以的,毕竟任何内容的引入都会产生额外的开销(运行层)。而如果大型项目的话,肯定是需要用到模板技术来进行管理的,一般情况下我们不需要自己开发模板引擎,可以用市场上现有的成熟的模板引擎,比如Smarty

Smarty模板引擎介绍

定义:Smarty是一个使用PHP写出来的模板引擎,是目前业界最著名的PHP模板引擎之一。它提供了逻辑与外在内容的分离,简单的讲,目的就是要使用php程序员同美工分离,使用的程序员改变程序的逻辑内容不会影响到美工的页面设计,美工重新修改页面不会影响到程序的程序逻辑,这在多人合作的项目中显的尤为重要。

  1. Smarty是一款专门用于PHP与HTML分离的模板技术,通常不会独立工作,而是在PHP项目需要使用的时候引入使用。我们可以从Smarty官网下载

5月13日学习 - 图1

注意:Smarty从2.6.31版本开始已经是基于PHP7.2版本,所以要根据实际PHP版本来选择对应的Smarty版本

  1. 任何工具的时候都可以从操作手册着手,Smarty有强大的操作手册,我们可以在开发的时候去寻找帮助

5月13日学习 - 图2

  1. 使用Smarty的优缺点
  • 优点
    • 效率高,这是Smarty模板引擎特有的,可以让我们的网站访问效率提升
    • 编译型,Smarty并非简单的替换,而是对模板先进行编译,从而达到效率高(二次访问不再编译)
    • 缓存,Smarty可以直接缓存,在编译的基础上生成访问效率更高的静态页
    • 插件,允许开发人员自定义插件(通常不用)
    • 灵活,内置函数可以方便开发人员高效率实现数据显示
  • 缺点
    • 数据实时效率低,如果访问数据是实时的,那么smarty会降低访问效率
    • 不适合小项目,会让项目开发难度增加,丧失PHP敏捷开发的特点

总结

  1. Smarty是一款致力于解决PHP和HTML分离的模板引擎
  2. Smarty能够很好的提升大项目的访问效率,但是也会增加开发成本,不适合小项目和数据实时性要求高的项目

Smarty的简单使用

定义:Smarty使用,就是将Smarty加入到项目中,并且引入到项目中实现模板替换的功能。

  1. Smarty作为一款插件,可以直接放到项目的根目录,也可以根据实际项目需求,放到相应的插件目录(Vendor)。当前作为学习,我们可以直接将Smarty放到网站根目录:从官网下载,然后解压,将解压后文件夹中的libs文件夹放到网站根目录,为了方便管理可以改名为smarty文件夹(目前使用的是最新版本3.1.32)

5月13日学习 - 图3

  1. Smarty被引入到项目之后,我们要做的就是去包含Smarty.class.php文件,然后进行实例化
  1. //加载Smarty类文件,实例化
  2. include_once 'smarty/Smarty.class.php';
  3. $smarty = new Smarty();
  1. Smarty的目标是将用户要显示的数据通过Smarty在模板合适的位置显示出来,这里要实现该功能一共分为三步
  • 在模板中使用Smarty规则来定义数据存放占位符:默认规则是{ + $ + 变量名 + }
  1. <!--smarty.html模板文件-->
  2. <!DOCTYPE html>
  3. <html>
  4. <head>
  5. <title></title>
  6. </head>
  7. <body>
  8. {$hello}
  9. </body>
  10. </html>
  • 使用Smarty::assign(‘模板中变量名’,’数据’)方法将要显示的数据传递给模板
  1. //接Smarty实例化对象后
  2. $smarty->assign('hello','具体数据');
  • 使用Smarty::display(‘模板文件’)方法将要显示数据的模板加载显示:默认加载路径是网站根目录或者根目录下的templates文件夹
  1. //接smarty的assign方法后
  2. $smarty->display('smarty.html');

总结

  1. Smarty可以直接从官网获取版本,版本使用请参照对应的PHP版本(最新版适用PHP7)
  2. Smarty虽然强大,但是使用步骤非常简单
  • 引入Smarty.class.php文件
  • 实例化Smarty对象
  • 利用smarty::assign()方法分配要给模板显示的数据
  • 利用smarty::display()方法加载模板文件
  • 在模板中利用smarty标记来占位数据(注意名字与assign方法分配的名字要一致,否则匹配不上)

Smarty配置

定义:Smarty配置,即根据项目具体需求,来选择smarty应该怎么样去工作。

  1. Smarty提供了很多配置,可以通过其Smarty对象的属性来设置。
  • $smarty->debugging = false; //是否开启debug调试,默认关闭
  • $smarty->template_dir = “templates/“; //模板目录
  • $smarty->compile_dir = “templates_c/“; //编译目录(Smarty自动创建)
  • $smarty->config_dir = “configs/“; //配置项目录
  • $smarty->caching = false; //是否开启缓存
  • $smarty->cache_dir = “cache/“; //缓存目录(开启缓存后自动创建)
  • $smarty->cache_lifetime = 3600; //缓存生命周期,单位是s
  • $smarty->left_delimiter = “{“; //左定界符
  • $smarty->right_delimiter = “}”; //右定界符
  1. 最简单的使用是只需要配置一下对应的template_dir属性即可
  1. $smarty = new Smarty();
  2. $smarty->template_dir = 'templates/'; //实际模板所在目录
  3. //注意:如果指定的目录不存在,那么系统还会自动去根目录下寻找
  1. 如果需要开启缓存,那么需要配置三项内容
  1. $smarty->caching = true;
  2. $smarty->cache_dir = 'cache/'; //后两项可以默认
  3. $smarty->cache_lifetime = 24 + 60 * 60;
  1. 如果考虑到{}作为模板分隔符会与js冲突的话,可以修改一下
  1. $smarty->left_delimiter = "<{";
  2. $smarty->right_delimiter = "}>";

总结

  1. Smarty配置提供了很多控制方式,我们可以根据自己的需求来设定控制
  2. 通常使用Smarty时,需要设置的就是模板路径template_dir和可能冲突的分隔符left/right_delimiter
  3. 在项目开发阶段,一般不会开启缓存模式;如果生产环境数据的变更不频繁,那么可以开启

Smarty模板技术详解

思考:Smarty中如果涉及到数组该怎么解析?是不是所有的变量,包括系统的预定义变量都需要进行assign然后才能解析?

引入:Smarty针对模板中的解析变量,做了自己的解析规则,默认的处理方式的确是行不通的,需要参照Smarty制定的变量规则。

Smarty模板引擎介绍

定义:Smarty是一个使用PHP写出来的模板引擎,是目前业界最著名的PHP模板引擎之一。它提供了逻辑与外在内容的分离,简单的讲,目的就是要使用php程序员同美工分离,使用的程序员改变程序的逻辑内容不会影响到美工的页面设计,美工重新修改页面不会影响到程序的程序逻辑,这在多人合作的项目中显的尤为重要。

  1. Smarty是一款专门用于PHP与HTML分离的模板技术,通常不会独立工作,而是在PHP项目需要使用的时候引入使用。我们可以从Smarty官网下载

5月13日学习 - 图4

注意:Smarty从2.6.31版本开始已经是基于PHP7.2版本,所以要根据实际PHP版本来选择对应的Smarty版本

  1. 任何工具的时候都可以从操作手册着手,Smarty有强大的操作手册,我们可以在开发的时候去寻找帮助

5月13日学习 - 图5

  1. 使用Smarty的优缺点
  • 优点
    • 效率高,这是Smarty模板引擎特有的,可以让我们的网站访问效率提升
    • 编译型,Smarty并非简单的替换,而是对模板先进行编译,从而达到效率高(二次访问不再编译)
    • 缓存,Smarty可以直接缓存,在编译的基础上生成访问效率更高的静态页
    • 插件,允许开发人员自定义插件(通常不用)
    • 灵活,内置函数可以方便开发人员高效率实现数据显示
  • 缺点
    • 数据实时效率低,如果访问数据是实时的,那么smarty会降低访问效率
    • 不适合小项目,会让项目开发难度增加,丧失PHP敏捷开发的特点

总结

  1. Smarty是一款致力于解决PHP和HTML分离的模板引擎
  2. Smarty能够很好的提升大项目的访问效率,但是也会增加开发成本,不适合小项目和数据实时性要求高的项目

Smarty的简单使用

定义:Smarty使用,就是将Smarty加入到项目中,并且引入到项目中实现模板替换的功能。

  1. Smarty作为一款插件,可以直接放到项目的根目录,也可以根据实际项目需求,放到相应的插件目录(Vendor)。当前作为学习,我们可以直接将Smarty放到网站根目录:从官网下载,然后解压,将解压后文件夹中的libs文件夹放到网站根目录,为了方便管理可以改名为smarty文件夹(目前使用的是最新版本3.1.32)

5月13日学习 - 图6

  1. Smarty被引入到项目之后,我们要做的就是去包含Smarty.class.php文件,然后进行实例化
  1. //加载Smarty类文件,实例化
  2. include_once 'smarty/Smarty.class.php';
  3. $smarty = new Smarty();
  1. Smarty的目标是将用户要显示的数据通过Smarty在模板合适的位置显示出来,这里要实现该功能一共分为三步
  • 在模板中使用Smarty规则来定义数据存放占位符:默认规则是{ + $ + 变量名 + }
  1. <!--smarty.html模板文件-->
  2. <!DOCTYPE html>
  3. <html>
  4. <head>
  5. <title></title>
  6. </head>
  7. <body>
  8. {$hello}
  9. </body>
  10. </html>
  • 使用Smarty::assign(‘模板中变量名’,’数据’)方法将要显示的数据传递给模板
  1. //接Smarty实例化对象后
  2. $smarty->assign('hello','具体数据');
  • 使用Smarty::display(‘模板文件’)方法将要显示数据的模板加载显示:默认加载路径是网站根目录或者根目录下的templates文件夹
  1. //接smarty的assign方法后
  2. $smarty->display('smarty.html');

总结

  1. Smarty可以直接从官网获取版本,版本使用请参照对应的PHP版本(最新版适用PHP7)
  2. Smarty虽然强大,但是使用步骤非常简单
  • 引入Smarty.class.php文件
  • 实例化Smarty对象
  • 利用smarty::assign()方法分配要给模板显示的数据
  • 利用smarty::display()方法加载模板文件
  • 在模板中利用smarty标记来占位数据(注意名字与assign方法分配的名字要一致,否则匹配不上)

Smarty配置

定义:Smarty配置,即根据项目具体需求,来选择smarty应该怎么样去工作。

  1. Smarty提供了很多配置,可以通过其Smarty对象的属性来设置。
  • $smarty->debugging = false; //是否开启debug调试,默认关闭
  • $smarty->template_dir = “templates/“; //模板目录
  • $smarty->compile_dir = “templates_c/“; //编译目录(Smarty自动创建)
  • $smarty->config_dir = “configs/“; //配置项目录
  • $smarty->caching = false; //是否开启缓存
  • $smarty->cache_dir = “cache/“; //缓存目录(开启缓存后自动创建)
  • $smarty->cache_lifetime = 3600; //缓存生命周期,单位是s
  • $smarty->left_delimiter = “{“; //左定界符
  • $smarty->right_delimiter = “}”; //右定界符
  1. 最简单的使用是只需要配置一下对应的template_dir属性即可
  1. $smarty = new Smarty();
  2. $smarty->template_dir = 'templates/'; //实际模板所在目录
  3. //注意:如果指定的目录不存在,那么系统还会自动去根目录下寻找
  1. 如果需要开启缓存,那么需要配置三项内容
  1. $smarty->caching = true;
  2. $smarty->cache_dir = 'cache/'; //后两项可以默认
  3. $smarty->cache_lifetime = 24 + 60 * 60;
  1. 如果考虑到{}作为模板分隔符会与js冲突的话,可以修改一下
  1. $smarty->left_delimiter = "<{";
  2. $smarty->right_delimiter = "}>";

总结

  1. Smarty配置提供了很多控制方式,我们可以根据自己的需求来设定控制
  2. 通常使用Smarty时,需要设置的就是模板路径template_dir和可能冲突的分隔符left/right_delimiter
  3. 在项目开发阶段,一般不会开启缓存模式;如果生产环境数据的变更不频繁,那么可以开启

Smarty模板技术详解2

模板变量

定义:模板变量,即在模板中被分配的变量,以及如何使用Smarty规则在模板中解析变量。

  1. 在Smarty模板中,我们将模板中的变量分为三类
  • PHP分配变量,即利用assign方法分配的变量
  • smarty保留变量,包括超全局预定义变量和smarty的内置变量
  • 自定义变量,用户在模板中去定义变量(通常不用)
  1. PHP分配变量,理论上PHP可以分配任意数据类型给模板进行解析,通常数据其实也就三种
  • 标量数据:直接使用标记输出的数据
  • 数组数据:在smarty模板中可以使用下标或者通过”.”+下标来实现
  • 对象数据:在smarty模板中也是通过对象访问符来实现访问
  1. //PHP给模板分配数据
  2. $smarty->assign('str','string');
  3. $smarty->assign('arr1',array(1,2,3)); //索引数组
  4. $smarty->assign('arr2',array('k1'=>'v1','k2'=>'v2')); //关联数组
  5. class Person{
  6. public $name = '张三';
  7. public $nickname = '小三';
  8. }
  9. $smarty->assign('person',new Person()); //对象
  10. $smarty->display('smarty.html');
  1. <!--smarty.html模板-->
  2. <html>
  3. <header></header>
  4. <body>
  5. {*smarty的注释:标量数据,直接显示即可*}
  6. 字符串:{$str}<br/>
  7. {*数组数据:两种下标访问方式都可以*}
  8. {$arr1[1]}---{$arr1.2}
  9. {$arr2.k1}---{$arr2['k2']}<br/>
  10. {*在Smarty中,"."模式用的比较多,但是一般索引数组不用点*}
  11. {*对象数据:直接按照对象访问方式访问即可*}
  12. {$person->name}---{$person->nickname}<br/>
  13. </body>
  14. </html>
  1. Smarty保留变量:是smarty考虑到用户会需要经常使用的系统变量,或者内部变量。这类变量通常以$smarty开始,然后是各类关键字,多次访问
  • GET数据:{$smarty.get.名字}
  • POST数据:{$smarty.post.名字}
  • session数据:{$smarty.session.名字}
  • cookie数据:{$smarty.cookies.名字}
  • REQUEST数据:{$smarty.request.名字}
  • server数据:{$smarty.server.大写名字}
  • 时间戳:{$smarty.now}
  • 模板路径:{$smarty.current_dir}
  • 模板名字:{$smarty.template}
  • 配置文件:{$smarty.config.配置名}
  1. <html>
  2. <header></header>
  3. <body>
  4. {*表单传递了数据:有get和post提交,开启了session,还有携带cookie*}
  5. GET数据:{$smarty.get.name}
  6. POST数据:{$smarty.post.name}
  7. session数据:{$smarty.session.username}
  8. cookie数据:{$smarty.cookies.username}
  9. REQUEST数据:{$smarty.request.name}
  10. server数据:{$smarty.server.SERVER_NAME}
  11. 时间戳:{$smarty.now}
  12. 模板路径:{$smarty.current_dir}
  13. 模板名字:{$smarty.template}
  14. </body>
  15. </html>
  1. 自定义变量:Smarty为了在模板中可以灵活的对数据进行处理,允许设置变量:{assign var=’变量名’ value=’变量值’}
  1. <html>
  2. <header></header>
  3. <body>
  4. {assign var='hello' value='world'}
  5. {$hello}
  6. </body>
  7. </html>
  1. 配置文件:在smarty中,提供了一种独立为Smarty提供个性化服务的配置文件。既然是模板技术,配置内容自然是为了改变模板效果。

配置文件格式:smarty的配置文件与PHP的配置文件不一样,通常可以直接使用txt格式文件。文件配置项的格式是名字 = 值,可以配置多个,#号代表注释,[局部]代表局部访问

  1. #注释:默认的,所有的配置项都是全局的:smarty_config.php
  2. bodyBgColor = #000000
  3. #局部配置
  4. [customer]
  5. pageTitle = 'Customer Info'

加载配置文件:当配置文件配置好之后,在模板中需要事先加载配置文件才能使用,使用{config_load file=’配置文件路径’ [section=’局部区间’]}

  1. {config_load file='smarty_config.php'}
  2. <html>
  3. <header></header>
  4. <body>
  5. </body>
  6. </html>

使用配置文件:当配置文件加载之后,smarty通过在标签内部使用一对“#”号来区分是配置文件,或者使用保留变量{$smarty.config.配置项名字}访问

  1. {*全局配置文件使用*}
  2. {config_load file='smarty_config.php'}
  3. <html>
  4. <header></header>
  5. <body bgcolor="{#bodyBgColor#}">
  6. </body>
  7. </html>
  1. {*局部配置文件访问*}
  2. {config_load file='smarty_config.php' section='customer'}
  3. <html>
  4. <title>{$smarty.config.pageTitle}</title>
  5. <body>
  6. </body>
  7. </html>

总结

  1. Smarty提供了多种在模板中显示数据的方式
  • PHP分配变量,在PHP中通过assign方法分配对的变量,在模板中直接使用
  • 内置变量,Smarty将各类系统超全局变量的内部实现,通过$smarty.超全局变量名[小写].数组元素下标访问
  • 自定义变量,在模板中可以通过{assign var=’变量名’ value=’值’}设定变量,并进行访问
  • Smarty允许对模板进行配置,可以通过smarty配置文件,{config_load file=”文件名” [section=’具体配置部分’]}的形式将配置文件引入到模板中,然后使用配置标签{#配置项#}或者保留变量{$smarty.config.配置项}来事项访问

内置函数

定义:Smarty内置函数,是Smarty针对分支、循环等数据处理语句封装的一套便于在模板中显示和操作数据的语法格式。

  1. 分支处理:Smarty中提供了一套if分支用于简单逻辑判定,语法格式为{if}{elseif}{else}{/if}
  1. <html>
  2. <header></header>
  3. <body>
  4. {if isset($smarty.post.username)}
  5. {$smarty.post.username}
  6. {else}
  7. 没有输入用户名
  8. {/if}
  9. </body>
  10. </html>
  1. 循环处理:PHP最核心的一点就是数据的批量输出,在Smarty中提供了多种遍历输出数组数据的方式
  • foreach:遍历所有类型数组,主要用户PHP分配的数据的输出显示
  1. <html>
  2. <header></header>
  3. <body>
  4. {形式1:采用foreach固有形式}
  5. {foreach $arr as $val}
  6. {*显示$val的数据*}
  7. {/foreach}
  8. {*形式2:采用smarty专属形式*}
  9. {foreach from=$arr key='键名字' item='值名字'}
  10. {*可以访问键名字和值*}
  11. {$键名字}{$值名字}
  12. <!--以下方式也能取得键名-->
  13. {$值名字@key}
  14. {/foreach}
  15. </body>
  16. </html>

注意1:在Smarty中,为foreach提供了很多可访问属性,通过{5月13日学习 - 图7循环值@属性}来实现访问

名字 含义
index 当前数组索引(循环内部)
iteration 当前循环的次数(循环内部)
first 首次循环(循环内部)
last 最后一次循环(循环内部)
show 循环是否执行判定:true表示循环有数据,false表示没有数据(未执行)
total foreach执行的总次数(循环内外都可以使用)
  1. <html>
  2. <header></header>
  3. <body>
  4. {assign var='user' value=array('username','age','gender')}
  5. <table border=1>
  6. {foreach $user as $value}
  7. {if $value@first} 第一次执行循环:
  8. <tr>
  9. <th>下标</th>
  10. <th>循环次数</th>
  11. <th></th>
  12. </tr>
  13. {/if}
  14. <tr>
  15. <td>{$value@index}</td>
  16. <td>{$value@iteration}</td>
  17. <td>{$value}</td>
  18. </tr>
  19. {/foreach}
  20. {if $value@show} 循环有数据,一共循环了{$value@total}次{/if}
  21. </table>
  22. </body>
  23. </html>

注意2:foreach还允许使用一种特定方式来处理foreach遍历的数组不存在的情况,使用{foreachelse}

  1. <html>
  2. <header></header>
  3. <body>
  4. {foreach from=$arr item='val'}
  5. {$val}
  6. {foreachelse}
  7. 没有数据o(╥﹏╥)o
  8. {/foreach}
  9. </body>
  10. </html>
  • section:遍历索引数组,通常更多的是用于没有分配数据的循环
  1. <html>
  2. <header></header>
  3. <body>
  4. {section name=任意名字 loop=传递数组|指定循环次数 [step=步长] [max=最大循环次数]}
  5. {$传递数组[section名字].遍历的元素下标}
  6. {/section}
  7. {assign var='arr' value=array(1,2,3,4,5,6)}
  8. {section name='id' loop=$arr max=4}
  9. {$arr[id]}
  10. {/section}
  11. </body>
  12. </html>

注意:与foreach一样,section也有很多属性,访问方式是{$smarty.section.section名字.属性}

名字 含义
index 当前数组索引(循环内部,受start和step影响)
index_prev 当前数组索引的前一个索引(受start和step影响)
index_next 当前数组索引的后一个索引(受start和step影响)
iteration 当前循环的次数,不受section的start和step影响,代表循环次数
first 首次循环,布尔值(循环内部)
last 最后一次循环,布尔值(循环内部)
rownum iteration别名
loop 最后一次循环的下标(循环内外都可以使用)
show 循环是否执行判定:true表示循环有数据,false表示没有数据(未执行)
total section执行的总次数(循环内外都可以使用)
  1. 文件包含:PHP实际开发中,为了维护的方便,会将模板或者其他文件拆分成多个,此时就需要用到文件的包含来使得最终模板完整。{include file=’模板文件’},将另外一个模板文件包含进来(通常是一部分)
  1. <div class='order'>
  2. <!--菜单部分-->
  3. </div>
  1. <html>
  2. <header></header>
  3. <body>
  4. <!--菜单部分-->
  5. {include file='order.html'}
  6. <!--主体部分-->
  7. <!--页脚部分-->
  8. </body>
  9. </html>
  1. 前端语法保护:smarty用到的标签很有可能与css样式和js冲突,此时smarty会错误的认为js或者css是smarty语法,而尝试去解析,这个时候就会报错。因此smarty提供了一种语法保护的方式,将可能冲突的部分包含起来,从而smarty不去解析:{literal}{/literal}
  1. <html>
  2. <header></header>
  3. <body>
  4. <div>
  5. <a href="javascript:show()">点我</a>
  6. </div>
  7. {literal}
  8. <script>
  9. function show(){
  10. alert('hello world');
  11. }
  12. </script>
  13. {/literal}
  14. </body>
  15. </html>

总结

  1. Smarty内置函数是指在模板中可以直接使用标签代替的形式去达到对应的效果
  2. Smarty中内置的函数有很多,常用的有以下几个:
  • 分支处理:{if}{elseif}{else}{/if}
  • 循环处理:{foreach from=数据源 item=值变量}{/foreach}
  • 循环处理:{section name=名字 loop=数据源/循环次数}{/section}
  • 文件包含:{include file=’路径’}
  • 语法保护:{literal}{/literal}
  1. Smarty内置函数循环处理有很多的属性,可以方便我们在进行表格处理、数据统计时作为数据支持

外部函数使用

定义:所谓外部函数使用,是指Smarty没有内置相应的函数,或者用户在PHP中自定义了一些函数,此时需要在模板中使用到。

  1. 系统函数使用:在模板中如果想要使用PHP系统函数,因为smarty的加工处理,所以需要对函数使用一个相应的边界符{}来包裹
  1. <html>
  2. <header></header>
  3. <body>
  4. 字符串abcdefg一共有{strlen('abcdefg')}个字节
  5. </body>
  6. </html>
  1. 自定义函数使用:用户自定义的函数使用,与系统函数一样
  1. //实例化Smarty
  2. include 'smarty/Smarty.class.php';
  3. $smarty = new Smarty();
  4. //自定义函数:也可以定义在smarty实例化之前,只需保证smarty加载模板之前已经进入内存即可
  5. function show(){
  6. echo __FUNCTION__;
  7. }
  8. $smarty->display('smarty.html');
  1. <html>
  2. <header></header>
  3. <body>
  4. {show()}
  5. </body>
  6. </html>

总结:Smarty中允许在模板中使用相应的系统函数和用户自定义函数,使用对应的smarty边界符标记好即可