在项目中,尤其是MVC的项目中,前段后后端的代码是分开的,
后端控制前段的代码只需要incdude 引入就可以,
那么前段的代码 里面包含<?php?>,需要怎么分离呢?
原理:
前段的人员都喜欢< p > < a > 这样的代码,那我们能不能使用{ }来替换呢?
这样做php 也解析不了{ }中的内容啊
<?php $name="小伟"; $age=32; include "my.html";
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> </head> <body> 姓名:{$name}<br> 年龄:{$age} </body> </html>
显示结果
姓名:{$name}
年龄:{$age}
那怎么做呢?
//查找和替换 $str=file_get_contents("my.html"); $str=str_replace('{','<?php echo ',$str); $str=str_replace('}','?>',$str); file_put_contents("my.html",$str); //包含师徒文件 include "my.html";
上面这样做,my.html的源文件也会改变,那下次访问的时候,就不行了 因为{ } 都已经替换成了 <?php?> 了
我们应该在file_put_contents 写到一个新的文件中 如new.html
模板引擎的原理,就是查找和替换
引入模板引擎
Smarty是属于外部提供的功能(插件),我们一般的做法是将其放到一个专门的目录里面(Vendor),该目录命名为Vendor也可以叫做Tools
第一步,在根目录下 创建Vendor,并把Smarty核心文件拷贝进去,并且设置基本目录常量、自动加载
在框架类中增加
private static function initConst(){ //定义基本目录常量 define("ROOT_DIR",str_replace('\','/',getcwd().'/')); define("APP_DIR",ROOT_DIR.'Applaction/'); define("FRAME_DIR",ROOT_DIR."Framework/"); define("CONF_DIR",APP_DIR."Config/"); define("VENDOR_DIR",ROOT_DIR."Vendor/"); //Vendor目录,每个平台都需要使用到 define("SMARTY_DIR",VENDOR_DIR."Smarty/"); //Smarty目录 }
自动加载类中
private static function auto_load($class){ //自动加载类 $frame_class=array( "Framework" => FRAME_DIR."Framework.class.php", "MyPDO" => FRAME_DIR."/MyPDO.class.php", "Factory" => FRAME_DIR."Factory.class.php", "Model" => FRAME_DIR."Model.class.php", "Conf" =>CONF_DIR."conf.php", "Smarty" =>SMARTY_DIR."Smarty.class.php" ); if(isset($frame_class[$class])){ require $frame_class[$class]; }elseif(substr($class,-10)=="Controller"){ require CURRENT_CON_DIR. "{$class}.class.php"; }elseif(substr($class,-5)=="Model"){ require CURRENT_MOD_DIR."{$class}.class.php"; } }
第二步;调用Smarty,因为各个平台都需要使用Smarty,所以在Controller基础控制器中引入
<?php //基础控制器所有控制器的父类 class Controller{ //定义一个属性,保存smarty protected $smarty; public function __construct(){ //初始化文件编码 $this->initCode(); //初始化Smarty $this->initSmarty(); } //所有子类控制器中需要使用的初始化文件编码 protected function initCode(){ header('Content-type:text/html;charset=utf8'); } protected function initSmarty(){ $this->smarty=new Smarty(); } }
第三步,在代码中应用smarty,
smarty常用的方法
assign 分配变量
display 输出模板
在MyuserController中
<?php //学生控制器 class MyuserController extends Controller{ public function showAction(){ $user=Factory::M('MyuserModel'); $rs=$user->select(); //把$rs变量分配给模板当中的rs来接受 $this->smarty->assign('rs',$rs); //输出模板 $this->smarty->display('myuser.html'); // include CURRENT_VIEW_DIR."myuser.html"; 这个就不需要了 } }
失败(Smarty: Unable to load template file 'myuser.html' ):为什么会失败,找不到temlate模板
因为Smarty默认的目录是在template目录下找,所以要重新设置一个默认的模板目录
为了方便管理,将view按照所属的控制器再次进行分类,就是在视图view目录下,再次建立相应的控制器名字作为子目录,
然后将其对应的视图文件放到不同的子目录下
目录就变成了这样
protected function initSmarty(){ $this->smarty=new Smarty(); //设置默认的模板目录, 当前目录下,control为myuser,前面确定分发定义过 $this->smarty->setTemplateDir(CURRENT_VIEW_DIR.CONTROL.'/'); }
不显示数据?为什么 有怎么了?
Smarty在编译模板文件的时候为了不影响原来的myuser.html原始的文件,在编译过程中会创建一个template_c的文件夹,找个文件夹下就是我们html+php编译后的文件
但是他会在根目录下创建有点不合适
我们应该跟各个平台下的view目录同级,名字叫做view_c,并且和view一样使用控制器作为子目录,以示区分。
第四步
优化smarty编译目录
protected function initSmarty(){ $this->smarty=new Smarty(); //设置默认的模板目录, 当前目录下,control为myuser,前面确定分发定义过 $this->smarty->setTemplateDir(CURRENT_VIEW_DIR.CONTROL.'/'); //设置编译目录,在当前平台下/viewz_c/的控制器myuser/ $this->smarty->setCompileDir(APP_DIR.PLATFORM."/view_c/".CONTROL.'/'); } }
第五步:
修改myuser.html视图文件,改成smarty风格的 不需要php代码了
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>学生列表</title> </head> <body> <style> th{ background-color: #f0f0f0; } </style> <table> <tr> <th>编号</th> <th>姓名</th> <th>地址</th> <th>性别</th> <th>年龄</th> <th>操作</th> </tr> {foreach from=$rs item='values'} <tr> <td>{$values.id}</td> <td>{$values.mingzi}</td> <td>{$values.home_add}</td> <td>{$values.sex}</td> <td>{$values.age}</td> <td><a href="index.php?p=Tset&c=Myuser&a=delete&id="{$values.id}>删除</a></td> </tr> {/foreach} </table> </body> </html>