黑马程序员技术交流社区

标题: 从小博客项目理解MVC设计模式 [打印本页]

作者: 蒋雷    时间: 2017-11-12 09:44
标题: 从小博客项目理解MVC设计模式
MVC是一种设计典范。
典范,是著名的设计模式。
MVC是一种著名的设计模式。

M:Model,即模型
V:View,即视图
C:COntroller,即控制

M负责操作数据库、V负责调用模板显示页面、C负责控制M与V。
通过一个小博客项目,深入的理解一下MVC设计模式(个人理解)
博客采用单一入口,所谓单一入口,就是所有的请求只能通过一个唯一的入口传递。

在入口中,引入了一个Frame.class.php文件
Frame.class.php是一个框架文件。

在框架文件中,大致可分为以下几个部分:

1、基本设置


进行一些必要的设置,如怎么样处理错误信息、使用什么字符集、加载需要使用的配置文件

2、URL指令解析


划重点:当用户通过页面点击某个功能(URL)时,浏览器会通过GET或者POST的方式,
将相关的数据传递到此处。

如: <form action="index.php?m=admin&c=Privilege&a=validate" method="post">

通过$_REQUEST函数获取相应的数值。

然后将其定义为常量(定义常量的好处是在整个项目中的任何一个位置都可以直接调用)

3、目录常量的定义


敲黑板划重点:当完成URL的解析后,通过规则进行拼接,获得不同的控制器、模型、视图的文件目录。

其中:
常量APP_PATH在入口文件处已经设定为常量,可直接调用。

M表示模型层,在Blog项目中,有Admin与Home两种,Admin表示后台,Home表示前端。
Controllers、Models、VIews表示不同功能的不同控制器、模型层、视图层存放的文件夹

所以:
DIR_CONT表示控制器的目录常量、DIR_MODEL表示模型层的目录常量、DIR_TMPL表示HTML模板的目录常量

另外:
DIR_FRAME表示当前文件的目录常量,仅包括文件夹,不包含文件
DIR_CORE表示核心文件目录常量
DIR_FMARTY表示Smarty模板目录常量

最后一个是实现文件上传时使用的文件上传目录常量

4、实例化控制器


不论是解析URL指令、还是定义相应的常量目录,最终的目的,都是为了实例化控制器做准备。

为什么要实例化控制器?

因为当用户点击页面的某个功能时,最终要完成相应的操作(如页面的跳转、数据的增删改查),都需要控制器的逻辑控制,或是调用视图层显示某个页面,或是调用模型层实现某个数据的操作等等。

而要使用控制层,那么就必须实例化控制层,而且是实例化相应功能的控制层(不同功能拥有不同的控制层),然后,通过对象调用相应的方法。

又因为,实例化的控制器不在同一命名空间,所以,实例化时,要加上命名空间。

此时注意:

此时还不一定能实例化成功,因为要实例化的控制器类与当前的Frame类并不在同一目录下,所以,还需要第五步操作。

5、自动加载


自动加载的主要作用,就是当我们实例化某个类时,如果没有找到该类,那么系统会自动通过autoload()方法去寻找该类。

6、调用


定义方法的最终目的是为了被调用实现某个功能



当一个从用户页面的URL被点击时,相应的指令被传递到入口文件,入口文件引入Frame类并调用的相应的方法(如run()),PHP脚本按照代码开始执行,解析URL指令、然后根据解析的结果定义相关的目录常量,然后根据不同的功能,实例化不同的控制器,当系统找不到需要的类时,自动加载功能启用,通过自动加载,找到相应的类并完成实例化,然后调用控制器中相应的方法,至此,Frame框架的任务完成,流程转入到控制器当中。


/**********************************控制层****************************/


当php脚本执行到控制层时,首先,第一件事情,找到指令当中的方法并执行。
如当前的登录方法,用于判断验证用户输入的登录信息


执行登录方法,然后对页面传递的数据进行接收并判断
(对每一个数据的合法性都需要进行判断,以防止脚本崩溃)
当PHP脚本执行到控制层时,通常会出现两种情况,一个中调用视图层显示某一个页面,一种是调用模型层对数据进行操作(增删改查)



/**********************************视图层****************************/

当调用视图层时,不用做任何其他操作,只需要通过$this调用view对象,然后调用display()方法,并且在display()方法中传递需要显示的html文件名即可。



这里,仍旧要补充说明,之所以不需要设置文件路径,是因为在View类中,已经设置好了html模板所在的路径,只需要设置html模板的文件名即可。

简单而优雅的流程图献上:



子类控制器继承父类控制器,父类控制器与VIew视图层同命名空间,可直接实例化视图层,而视图层继承Smarty模板,因为,在子类控制器中可直接使用视图层的对象调用Smarty中的方法。

如图:VIew类



/**********************************模型层****************************/

当调用模型层时,需要引入该模型层的命名空间,然后对其进行实例化,最后通过对象调用模型层的相关方法,如果需要传递参数,则传递参数,如果有返回值,则接收返回值。


PHP脚本执行至模型层,调用相应的方法,在这里,需要定义SQL语句,通过操作数据库的方法对数据库进行操作。

操作数据库时,使用由自己封装好的MyPDO类进行操作(包括增删改查)


具体的流程:

在控制层中,实例化模型层对象,然后调用模型层的方法,通过模型层的方法,对数据库进行操作


最后,模型层通过PDO类对数据操作完毕,PDO返回结果至模型层,模型层继续返回至控制层,控制层将数据传递至视图层,然后调用视图层,进行一次周期的循环


在整个MVC模式中,不同的层级负责不同的功能,就像是一个职责明确的军队一样。

C层是一个指令传达中心,当军队的前线(即前端)需要某个后援部队支援时(执行某个功能)

首先传达至专解密部(Frame框架),通过对指令的解析,得出下一步需要的操作

然后解密部将命令交给指令传达中心,指令传达中心对向相应的部队下达指令(V或M)

相应的部队根据指令,执行各自内部的执行流程,得到结果后,反馈给指令传达中心

指令传达中心根据反馈结果进行接下来的操作(同样时继续调用视图层或者模型层,永远都不会超出这两个层级)

在模型层与视图层执行某项功能时,通常还需要调用其他已经封装好的类库,如:验证码、图片上传、图片的处理等等。

调用已封装的类库,就如同某个部队在执行某项任务时,需要请求更加专业的其他部队进行协助,以便更好的完成任务。例如空军在执行某项飞行任务时,需要专业的气象部队进行气象情况的协助。

整个MVC模型,大致就是如此。C层负责控制、V层负责显示、M层负责操作数据库,还有一些辅助的类库,以便于整个程序能够更加健壮的运行。

最后,完整版MVC流程图


来自深圳PHP8 期,蒋雷,欢迎同学交流(微信:isjianglei)。








欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2