【叶凡网络】关于PHP框架中的MVC模式及单一入口的分析

2014-03-13 13:27:39 | 新闻来源:叶凡网络 | 点击量:1119

关于MVC,只是简单介绍,这里不详细讲解何为MVC模式.关于MVC具体信息可以去网络上找寻,MVC模式在理解来它将一个项目分解成三部分,分别是Model模型),View视图),Control控制器),这三个单词的缩写组合即为MVC.MVC一种普遍的软件敏捷开发模式,许多领域特别是桌面编程领域早已经得到广泛的应用,然而在像php一样的脚本语言中比较难以实现,特别是几年前在脚本语言中很难看到MVC实现,但是今年随着众多框架的涌现,MVC各个框架中得到初步实现,其他框架中的实现方式暂且不提,这里只是介绍codeignit如何实现MVC.

关于单一入口,所有的请求都是指向一个脚本文件的,单一入口指在一个网站(应用顺序)中.例如CI中的http:\\localhost\index.php,所有对应用程序的访问都是必需通过这个入口,正是单一入口才使得MVC模式得以实现,因为当你访问index.php时候,应用顺序会做大量的初始化工作,调用大量的基础类库,并根据index.php后面的参数加载控制器,然后加载试图,模型等内容信息.因为控制器是CI中的超类,ci所有文件加载都要经过控制器调用.也就是其他类都依附于它,所以用单一入口方式访问CI应用顺序的时候,需要在index.php后面加上控制器名和控制器中的方法名,如果你对于此没有任何概念或者无法理解,可以去CI官方网站下载它官方文档,然后详细了解它工作方式

这里描述的文档上所不存在基本原理局部CI官方文档非常详尽易懂.CI中的一个控制器就是用户编写的一个类,或许应该先讲解CI控制器是如何工作的.继承自系统的Control类,例如假设我要构建一个可以通过http:\\localhost\index.php\control\func\param1\param2访问的页面,需要做哪些工作呢,首先我要在system\application\controllers\文件夹下新建一个文件contro.php文件,这个文件即是要访问的控制器类所在文件,此文件中创建以下内容:

$param29    {10  $this->load->model'MSomemodel',1classControlextendControl{23    functionControl4    {5        parent::Control;   6    }7    8    functionfunc$param1.'',PUE;11  $data['data1']=$this->MSomemodel->getvalu;12           $this->load->view'welcome',$data;13    }14}15 

而是包括了model和view一个控制器例子,这并不是一个控制器的基本组成局部.然后在类的构造函数里应该调用父类的构造函数,首先注意控制器的类名应该是首字母大写的.之后则是func方法,也就是url后面所带参数的第二个部分,这个方法带有两个参数,这两个参数的值就是url第三局部和第四部分的值,也就是单一入口的访问方式实际是:http:\\localhost\index.php\控制器名\方法名\方法的参数1\方法的参数2\......

也就是可以将很多类似的操作放到一个控制器中,控制器类中每个方法代表一个页面.实现对操作的统一,加载model时候加载的model文件夹中的msomemodel.php文件中的MSomemodel类,上述的例子中的func方法中的其他局部分别加载了model和view.这个类负责应用顺序的模型局部,也就是负责数据的交换,例如数据库的存储.

并从这个方法返回了数据,然后我通过$data=$this->MSomemodel->getvalu执行了model中的一个方法.然后赋值给$data['data1'],$data一个关联数组,通过这个数组向view视图文件传值,而不是使用罕见的模板模式,这种方法更好地分离了MVC各个局部的处置,同时在性能方面有其独特的一面.这个文件是惯例的php和html混写的脚本,之后我通过将$data数组传给view文件夹中的welcome.php文件.这个脚本中可以利用传过来的$data数组输出信息,但是注意在view文件中输出信息的时候不必使用$data['data1'],而只需要echo$data1;即可.下面从代码级别来分析实现基本的工作方式就是这样的.

代码分析,也就是所有加载MVC实现模式的进程都从Control类开始,CI中将Control类作为超类来处理.所以我忽略CI加载到这个类的时刻前面的执行过程,而直接从Control类所在文件开始分析.Control类所在文件位于system/libraries/Controller.php文件中.包括:'Config',这个类中首先加载了所有必需的基础类.'Input','Benchmark','URI','Output','Language','Router'类.之后加载Roader类并执行了_ci_autoload方法,这个类是MVC模式的核心,控制器中所有其他内容的加载都是通过它实现的,下面对其代码进行分析:这个函数实现了自动加载某些类库或者类,首先来看 _ci_autoload方法.如果在应用顺序中总是要用到某些类,但是又不确保在CI中是否已经自动加载了这些类的话,可以在config/autoload.php文件中设定要自动加载的librari或者helper或者plugin数组.具体请参考手册.

这个方法允许你控制器的任何地方(通常是构造函数里)使用$this->load->librari"name";来加载某个类,首先看看CI如何加载librari.这个类可以是用户自定义的类也可以是系统的类库,用户自定义的类需要遵循CI约定,具体信息见手册中的"创立你自己的类库 "局部.librari方法以一个字符串或者一个类库名称的数组作为第一个参数,之后的处置将遍历然后加载所有的类,可以通过第二个参数向要加载的类的构造函数传送参数,第三个参数允许你定义返回的对象的名称,后面的两个参数通常不使用,这个方法在简单判断了参数是否为空之后调用了方法_ci_load_class$class,$param=NULL,$object_nam=NULL,这是一个非常复杂的函数,这个类加载第一个参数所指定的类,这个类中进行了复杂的路径判断之后找到所需要的类文件之后,调用了方法_ci_init_class$class,'',$params,$object_nam;这个类用来实例化一个类,如果在加载这个类的语句中包含了上述的第三个参数,则返回一个实例,以这个参数作为实例名,如果没有设置第三个参数,则返回一个以类名命名的实例名,这也是为什么前面的例子中在加载了model之后,直接将model类名作为一个对象使用的原因.

这个方法允许你控制器中使用$this->load->model$modelname,之后我来看CI如何加载模型的.$name,$db_conn加载模型,这三个参数分别是加载的模型的名称,加载后实例化的对象名称,否自动连接数据库.后面两个参数可以省略,可以讲多个模型一次载入,只需要将第一个参数设置成数组即可,这个方法首先将传过来的第一个参数以"\"分解成数组,这种机制允许你模型中创建多层文件夹,更加合理地安排代码的分组,之后顺序取出数组的最后一个元素作为要加载的类的名称,并根据路径寻找此类,之后包括此文件,并实例化此类,如果设置了第二个参数,则实例化到$name对象中,否则默认以类名作为对象名进行实例化.

再来看CI如何加载视图的,view$view,$var=arrai,$return=FA LSE方法的第一个参数是要加载的视图名称,第二个参数是要传给视图的变量值,第三个参数指定是否返回输出缓冲区的数据.这个方法将所有数组作为一个数组参数调用了_ci_load$_ci_data方法,这个方法将传过来的变量数组通过extract函数解析成符号表(也就是将键名当作变量名。并将这些变量缓存起来,以便可以再不同的视图中能够互相交流变量,也就是这个方法允许调用多次,为了每次调用时都能自动加载已经传给前面视图的变量,将所有传给视图的变量都缓存在类的一个属性中,这样每次调用方法的时候都会获取所有的变量.之后加载这个视图文件,然后将其作为输出缓冲的一局部赋给全局变量$OUT,这个变量用来控制缓冲输出,这样做可以提高效率以及可以使调试的时间更准确.

只是根据情况有少许改变,其他加载方法和上述的方法原理基本相同.CI实现MVC模式的方法中将所有的文件都包含在控制器中,包括了这些文件后,可以再控制器中自由使用这些对象和数据,然后最后通过缓冲输出类来输出所有的数据,虽然Loader这个类的结构看起来很复杂,但是其实它实现时很简单的,其内部的代码原理基本相同,而且清晰明了,仔细看的话不难理解.

上一篇:【叶凡网络】备份Mysql数据库,用PHP实现XML 下一篇:【叶凡网络】十二届全国人大李克强总理会见中外记者,二次会议闭幕