PHP MVC框架 视图之常用学习笔记
今天来讲讲view,视图。。。没了解之前,你可能觉得模板引擎很神奇,了解了之后你会觉得,原来是如此简单。。。
对于模板引擎而言,它的原理一般是这样,把模板引擎的语言替换成可执行的语言,然后把变量输出。。。
因为PHP本身就是一个良好了模板引擎,所以用原生的模板引擎是灰常方便和容易做到的。。。
index.html
代码如下 | 复制代码 |
<html> <head> <title><?php echo $title ?></title> </head> <body> <h1><?php echo $content ?></h1> <?php if( ! empty($arr)) { ?> <ul> <?php foreach($arr as $value) { ?> <li><?php echo $value ?></li> <?php } ?> </ul> <?php } ?> </body> </html> |
想上面这样一个html页面,采用的就是原生的php模板引擎,服务器在你include这个页面时,会处理html中的PHP代码。
你也许会问,要是我想定制模板语言可以吗?答案当然是可以的,像我上面说的,用模板引擎的语言,只需要多做一步,就是把模板引擎的语言替换成标准的PHP语言。。。
index_2.html
代码如下 | 复制代码 |
<html> <head> <title><?php echo $title ?></title> </head> <body> <h1><?php echo $content ?></h1> <ifexist arr> <ul> <for value = arr> <li><echo value></li> <endfor> </ul> <endexist> </body> </html> |
看看这个页面,发现和index.html 有什么不同吗,没错,就是在循环那里,我们用的不是标准的php语言,而是,按照自己的喜好,定义了几个模板语言,一个是<ifexist xxx>这个是判断xxx变量是否存在,而且不为空,后面那个<for xx1=xx2>是循环迭代xx2变量,中间的<echo xx> 是输出xx变量
怎么替换成标准语言呢?这个可以使用正则替换,因为字符串替换无法满足我们需求了。
代码如下 | 复制代码 |
$pattern = array( ‘/<ifexists+(w+)>/i’, ‘/<fors+(w+)s=s(w+)>/’, ‘/<echos+(w+)>/’ ); $replacement = array( ‘<?php if( ! empty($\1)){ ?>’, ‘<?php foreach($\2 as $\1){ ?>’, ‘<?php echo $\1 ?>’ ); $content = preg_replace($pattern, $replacement, $content); $search = array(‘<endexist>’, ‘<endfor>’); $content = str_replace($search, ‘<?php } ?>’, $content); |
上面的正则就可以帮我们把刚刚定义的标签,转换成标准p hp语言。。。
转换之后是这样,请看图。
转换之后可以输出了吗?答案是不行的,因为你获取到html文件的内容的时候,php就已经解释了,那时候你还没替换成标准的php语言,所以,你现在输出的话,其中的php代码就没有执行。。。不过我们可以利用 php eval 这个函数,来强制要求执行其中的代码。
代码如下 | 复制代码 |
$content = eval(‘ ?>’.$content); |
注意哦,要 ?>.$content 要不,php会把其中的html当成是php代码的执行,这样就会出错了。。。
刷新一下,ok,已经可以执行了~~~
本文章来给各位介绍PHP MVC框架之加载器学习笔记,有需要了解的朋友可进入参考。上节说了MVC的路由原理,这节我们来说说MVC框架的loader,也称为加载器。
虽然不同的框架,加载器的用法不同,但是其原理都是相通的。。。都是通过单例模式加载文件,而且把已加载的文件cache起来,避免重复加载。。。因为在开发业务的过程中,常常需要加载不同的模块,不同的类库等,MVC的loader可以帮助我们实现单例模式,更加符合开发需求。
下面我们开始动手,利用其原理,做一个简单的loader。
首先,我们设计的加载器,要满足可以全局使用,无论在controller里还是在model、library里都可以使用。
其次,加载器要有缓存能力,即相同的文件只加载一次,相同的类只实例化一次。
最后,要能加载多种文件,model、library、helper。
先解决第一步,怎么全局使用,最简单的办法就是定义一个全局的function,这样,在后面的不同类库,不同function里都可以调用这个全局function,进行加载文件。
第二步和第三步,要一起解决,定义一个单例模式的loader类,因为是单例模式,可以保证全局只有一份内容,这样的话,就可以利用数组把这些已加载的内容和对象cache起来,这样就可以避免了重复加载的问题。。。
代码如下 | 复制代码 |
if ( ! function_exists(‘load’)) { function load($name, $type=’model’, $data=array()) { static $loader = NULL; if (is_null($loader)) { include (ROOT.’/system/core/loader.php’); $loader = Loader::get_instance(); } return $loader->$type($name, $data); } } |
上面这个,就是我写的一个简单的全局函数 load,这个函数的作用就是为了可以全局调用,然后通过这个load函数,去调用loader类,由loader类负责加载文件,实例化,和缓存对象。。。下面我把loader的代码放出来给大家看看。
代码如下 | 复制代码 |
<?php class Loader { private $_loaded_models = array(); private $_loaded_librarys = array(); private static $OBJ; # 单例模式,不允许new对象 private function __construct() { } public static function get_instance() { if (is_null(self::$OBJ)) { $class = __CLASS__; self::$OBJ = new $class; } return self::$OBJ; } public function model($model, $data=array()) { $model = strtolower($model); # 如果已经加载,则返回对象,避免重复加载 if (isset($this->_loaded_models[$model])) { return $this->_loaded_models[$model]; } # 否则加载文件 include ROOT.“/application/models/{$model}.php”; $class = ucfirst($model); # 实例化对象 if (emptyempty($data)) { $instance = new $class; } else { $instance = new $class($data); } # 把对象cache起来 $this->_loaded_models[$model] = $instance; return $instance; } public function library($library, $data=array()) { $library = strtolower($library); # 如果已经加载,则返回对象,避免重复加载 if (isset($this->_loaded_librarys[$library])) { return $this->_loaded_librarys[$library]; } # 否则加载文件 include ROOT.“/application/librarys/{$library}.php”; $class = ucfirst($library); # 实例化对象 if (emptyempty($data)) { $instance = new $class; } else { $instance = new $class($data); } # 把对象cache起来 $this->_loaded_librarys[$library] = $instance; return $instance; } } ?> |
大家看到了没有,这个loader采用的是单例模式,虽然前面的function的设计已经可以保证不会重复实例化loader这个对象,但是为了真正可以保证全局只有一份loader对象,设计成单例模式是最保险的。。。
具体的测试例子请看代码。。。我把代码打包上传上来,有需要的就下载回去看看吧。。。下载后,解压,把lesson2文件夹放到你的www目录下,然后访问yourdomain/MVC/lesson2/index.php/index/test 试试看吧。。。
文章主要讲到关于php中慎用isset来判断数组是否存在key一些举例说明。接上代码, 不知道是php5.4版本的问题, 还是本来就这样…
代码如下 | 复制代码 |
$a['hello'] = ’123‘; |
代码如下 | 复制代码 |
<?php /** * 下面提到的代码在PHP5.3以上版本运行通过. */ function callback($callback) { $callback(); } //输出: This is a anonymous function.<br />/n //这里是直接定义一个匿名函数进行传递, 在以往的版本中, 这是不可用的. //现在, 这种语法非常舒服, 和javascript语法基本一致, 之所以说基本呢, 需要继续向下看 //结论: 一个舒服的语法必然会受欢迎的. callback(function() { print "This is a anonymous function.<br />/n"; }); //输出: This is a closure use string value, msg is: Hello, everyone.<br />/n //这里首先定义了一个闭包, 这次户口本上有名字了... //use, 一个新鲜的家伙... //众所周知, 闭包: 内部函数使用了外部函数中定义的变量. //在PHP新开放的闭包语法中, 我们就是用use来使用闭包外部定义的变量的. //这里我们使用了外部变量$msg, 定义完之后, 又对其值进行了改变, 闭包被执行后输出的是原始值 //结论: 以传值方式传递的基础类型参数, 闭包use的值在闭包创建是就确定了. $msg = "Hello, everyone"; $callback = function () use ($msg) { print "This is a closure use string value, msg is: $msg. <br />/n"; }; $msg = "Hello, everybody"; callback($callback); //输出: This is a closure use string value lazy bind, msg is: Hello, everybody.<br />/n //换一种引用方式, 我们使用引用的方式来use //可以发现这次输出是闭包定义后的值... //这个其实不难理解, 我们以引用方式use, 那闭包use的是$msg这个变量的地址 //当后面对$msg这个地址上的值进行了改变之后, 闭包内再输出这个地址的值时, 自然改变了. $msg = "Hello, everyone"; $callback = function () use (&$msg) { print "This is a closure use string value lazy bind, msg is: $msg. <br />/n"; }; $msg = "Hello, everybody"; callback($callback); //输出: This is a closure use object, msg is: Hello, everyone.<br />/n //闭包中输出的是之前被拷贝的值为Hello, everyone的对象, 后面是对$obj这个名字的一个重新赋值. //可以这样考虑 //1. obj是对象Hello, everyone的名字 //2. 对象Hello, everyone被闭包use, 闭包产生了一个对Hello, everyone对象的引用 //3. obj被修改为Hello, everybody这个对象的名字 //4. 注意, 是名字obj代表的实体变了, 而不是Hello, everyone对象, 那自然闭包的输出还是前面的Hello, everyone $obj = (object) "Hello, everyone"; $callback = function () use ($obj) { print "This is a closure use object, msg is: {$obj->scalar}. <br />/n"; }; $obj = (object) "Hello, everybody"; callback($callback); //输出: This is a closure use object, msg is: Hello, everybody.<br />/n //还是按照上面的步骤, 按部就班的来吧: //1. obj名字指向Hello, everyone对象 //2. 闭包产生一个引用指向Hello, everyone对象 //3. 修改obj名字指向的对象(即Hello, everyone对象)的scalar值 //4. 执行闭包, 输出的自然是Hello, everybody, 因为其实只有一个真正的对象 $obj = (object) "Hello, everyone"; $callback = function () use ($obj) { print "This is a closure use object, msg is: {$obj->scalar}. <br />/n"; }; $obj->scalar = "Hello, everybody"; callback($callback); //输出: This is a closure use object lazy bind, msg is: Hello, everybody.<br />/n //闭包引用的是什么呢? &$obj, 闭包产生的引用指向$obj这个名字所指向的地址. //因此, 无论obj怎么变化, 都是逃不脱的.... //所以, 输出的就是改变后的值 $obj = (object) "Hello, everyone"; $callback = function () use (&$obj) { print "This is a closure use object lazy bind, msg is: {$obj->scalar}. <br />/n"; }; $obj = (object) "Hello, everybody"; callback($callback); /** * 一个利用闭包的计数器产生器 * 这里其实借鉴的是python中介绍闭包时的例子... * 我们可以这样考虑: * 1. counter函数每次调用, 创建一个局部变量$counter, 初始化为1. * 2. 然后创建一个闭包, 闭包产生了对局部变量$counter的引用. * 3. 函数counter返回创建的闭包, 并销毁局部变量, 但此时有闭包对$counter的引用, * 它并不会被回收, 因此, 我们可以这样理解, 被函数counter返回的闭包, 携带了一个游离态的 * 变量. * 4. 由于每次调用counter都会创建独立的$counter和闭包, 因此返回的闭包相互之间是独立的. * 5. 执行被返回的闭包, 对其携带的游离态变量自增并返回, 得到的就是一个计数器. * 结论: 此函数可以用来生成相互独立的计数器. */ function counter() { $counter = 1; return function() use(&$counter) {return $counter ++;}; } $counter1 = counter(); $counter2 = counter(); echo "counter1: " . $counter1() . "<br />/n"; echo "counter1: " . $counter1() . "<br />/n"; echo "counter1: " . $counter1() . "<br />/n"; echo "counter1: " . $counter1() . "<br />/n"; echo "counter2: " . $counter2() . "<br />/n"; echo "counter2: " . $counter2() . "<br />/n"; echo "counter2: " . $counter2() . "<br />/n"; echo "counter2: " . $counter2() . "<br />/n"; ?> |
为什么有些人php代码最后不加“?>”呢?起初我也不知道,后来百度了才知道。网上看教程,别人都有“?>”结束标签,但是看别人的源码很多人都没有加,原来不加结束标签可以避免尾部的空白字符意外输出,对代码产生某些不必要的影响。
相关文章
基于BootStrap Metronic开发框架经验小结【八】框架功能总体界面介绍
这篇文章主要介绍了基于BootStrap Metronic开发框架经验小结【八】框架功能总体界面介绍 的相关资料,需要的朋友可以参考下...2016-05-14- 首先来看下流程:流程原理: 1.通过code获得access_token通过授权,并获取用户的信息(包括用户u_id)(这个u_id在后面的第三方登录表里面叫sina_id,那个表是需要自己建的) 2.查询第三方登录表,如果不存在用户sina_id,分2...2014-05-31
- 这篇文章主要介绍了.net数据库操作框架SqlSugar的简单入门,帮助大家更好的理解和学习使用.net技术,感兴趣的朋友可以了解下...2021-09-22
- 这篇文章主要介绍了记一次EFCore类型转换错误及解决方案,帮助大家更好的理解和学习使用asp.net core,感兴趣的朋友可以了解下...2021-09-22
- 我们在php中上传文件就必须使用#_FILE变量了,这个自动全局变量 $_FILES 从 PHP 4.1.0 版本开始被支持。在这之前,从 4.0.0 版本开始,PHP 支持 $HTTP_POST_FILES 数组。这...2016-11-25
- 1、简介Smarty是一个使用PHP写出来的模板PHP模板引擎,是目前业界最著名的PHP模板引擎之一。它分离了逻辑代码和外在的内容,提供了一种易于管理和使用的方法,用来将原本与HTML代码混杂在一起PHP代码逻辑分离。简单的讲,目...2014-05-31
- 这篇文章主要介绍了c# 常用框架汇总,帮助大家更好的理解和学习使用c#,感兴趣的朋友可以了解下...2021-04-24
- 本文主要介绍AngularJS 视图,这里整理了相关知识,并附代码示例和实现效果图,有兴趣的小伙伴可以参考下...2016-08-27
- Laravel框架我们用到的不多了,但如果使用需要搭配了,下面我们来看一篇关于搭建php Laravel框架教程详解,具体的操作细节如下所示,希望对各位有帮助。 一、安装 Compos...2016-11-25
- 当我们在星际中开地图和几家电脑作战的时候,电脑的几个玩家相当于结盟,一旦我们出兵进攻某一家电脑,其余的电脑会出兵救援。 那么如何让各家电脑知道自己的盟友被攻击了...2016-11-25
- 这篇文章主要介绍了Java SSM框架如何添加写日志功能,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下...2020-09-25
ASP.NET中iframe框架点击左边页面链接 右边显示链接页面内容
这篇文章主要介绍了ASP.NET中iframe框架点击左边页面链接,右边显示链接页面内容的实现代码,感兴趣的小伙伴们可以参考一下...2021-09-22- 举一个简单的date例子 我将使用echo命令把内容输出到我们的客户端(浏览器)。我将使用下面的代码做为基础代码。 代码如下 复制代码 <!DOCTY...2016-11-25
- 这篇文章主要介绍了node.js爬虫框架node-crawler的相关资料,帮助大家利用node.js进行爬虫,感兴趣的朋友可以了解下...2020-10-29
- 这篇文章主要为大家详细介绍了iOS实现圆角箭头视图,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2021-04-16
- Ray是一种分布式执行框架,便于大规模应用程序和利用先进的机器学习库,今天给大家分享支持python的分布式计算框架Ray详解,感兴趣的朋友一起看看吧...2021-07-29
- 第一次接触神奇的vue.js,主要了解一下v-model、v-if、v-else、v-show、v-for等,感兴趣的小伙伴们可以一起学习一下...2016-12-02
BootStrap框架个人总结(bootstrap框架、导航条、下拉菜单、轮播广告carousel、栅格系统布局、标签页tabs、模态框、菜单定位)
这篇文章主要介绍了BootStrap框架个人总结(bootstrap框架、导航条、下拉菜单、轮播广告carousel、栅格系统布局、标签页tabs、模态框、菜单定位)的相关资料,需要的朋友可以参考下...2016-12-02- 这篇文章主要介绍了上手简单,功能强大的Python爬虫框架——feapder的使用教程,帮助大家更好的利用python进行爬虫,感兴趣的朋友可以了解下...2021-04-26
- 这篇文章主要介绍了初识angular框架后的所思所想,学习认识angular后的一些个人问题总结,需要的朋友可以参考下...2016-02-21