能简单解释一下MVC吗?越简单越好

最近打算学习PHP框架,才发现我以前对MVC的认识很肤浅。但是看Laravel的文档,对MVC又是云里雾里的

阅读 22.8k
17 个回答

比如说写一个 Todo List, 按照前端的 MVC 这样写:

  • Model: 一个 JSON 数组, 对应存在数据库的内容, 就是文本啊, 完成状态
  • View: HTML 模版, 或者 DOM 模版, 也就是界面
  • Controller: 用户在界面上操作, 进而对 Model 进行更改的操作

一般有这样的关系(不是很准确, 而且各种 MVC 实现也不完全一致):

  • 整个程序围绕 Model 的改变来更新
  • View 根据 Model 渲染, 随着 Model 更新而更新
  • Controller 接收 View 当中的事件触发, 对 Model 进行修改

整体上是一个循环~ 从 Model 开始, 中间加上用户操作, 又作用回到 Model
这是写图形的一个思路, 就是把数据跟界面区分开来, 简化程序.
或者说, 抽象出表示一个界面最少的数据作为 Model, 最少的操作作为 Controller.
而 View, 跟着 Model 变, 甚至根据用户需要随意进行改变.

大致上:

或者:

以下答案属个人见解,若有错求大神指正。

先说下原生PHP吧。
数据处理,页面显示在一起,互相嵌套。


MVC就不一样,数据处理和展示是分开的。
业务不复杂的时候基本V和C就能搞定。
C哥把数据处理好,打包交给V。郑重的给V说:“V哥,数据都在这里了,您拿去显示吧!”
V说:“好的C哥!” 然后就把数据展现在前端。V哥也有类似foreach等的语法,用来展示C哥给的数据。

有时候业务复杂了,C哥一个人处理数据有点累,C哥就喊M哥来帮忙。
M哥帮C哥做一些重复性工作,处理好后给C哥。再由C哥转交给V哥。


原生PHP就像外包,往往一个人就得处理前端后端的东西。
MVC就像一个成熟的公司,有前端有后端。分工明确。

概念大家都说了,其实MVC的涵义一直在潜移默化地变化,原本CS软件的MVC和如今php ruby python讲的MVC已经有不小的区别了。甚至很可能概念早就变成MVP,只是大家习惯了MVC,指鹿为马了

我觉得已实际项目来说,作3个思想实验就能大致理解MVC的本质和目标,具体三层怎么分,是三层还是四层还是两层,其实都是为了达成灵活性和可维护性的手段而已

更换数据库选择

数据结构不变,把数据库从mysql迁移到pgsql乃至mongodb,你的项目需要多大的变化?
理想的MVC架构应该无需修改任何业务代码(包括Model),只需要修改配置文件,最多写个新的DBAL driver
实际情况下不同DB的能力有微妙的区别,那也应该微调Model就能解决。

如果你的答案是两眼一黑:和重写一遍差不多,那么你的M层还不够独立,该写在Model的代码分散到别处了

手机HTML5版本

假设保持所有功能不变(都有合理自然的移动版交互),给你的站点增加手机版,你的项目需要多大的变化?
答案应该是重写一套View,然后Controller改一行if(isMobile) use(MobileView);

如果你发现Controller要改大量逻辑,甚至Model都被牵连,那你的V层不够独立

增加API

假设所有功能不变,给你的站点增加开放API(给第三方或移动应用使用),你的项目需要多大的变化?
答案应该是一套新的Controller 包含新的授权、和数据格式以及校验等逻辑,和一个简单的View(只输出json或xml)

如果你发现Model要改,原来View里的一些东西要挪动,或者是原来写在老的Controller里的部分代码要copy一遍,那么你的C层不够独立

最形象最简单的莫过于把MVC比作小时候玩的插卡式的游戏机:
M:就是游戏卡,保存数据,负责业务逻辑等
V:就是电视机,负责呈现游戏的画面
C:就是游戏控制手柄,负责前两者之间的交互

拿一个购物网站举例。
M提供了数据模型,比如网站的用户数据包括用户名,密码,邮箱,每个用户可以下多个订单,每个订单有订单号,价格等等。
V提供了视图,就是你看到的HTML界面是什么样的,比如商品列表的呈现,个人历史订单的呈现。
C是控制器,负责从M中提取数据,然后在V中如何呈现。比如你要查看最近一周个人订单历史的时候,V负责从M中找到你所有的订单,过滤掉一周以前的订单数据,然后把剩下的提供给V来展示。

理解mvc的前提是有代码分层的概念,而代码分层的目的是解耦。

请试图解答两个问题:

  1. 代码为什么要解耦?
  2. 如何解耦?

代码为什么要解耦

一个软件从用户触发视图上的业务需求,到程序按照一定的业务逻辑处理这个需求,再到将处理结果在视图的上反馈给用户,整个过程中的代码负责的主要任务有三个切面,即:视图的操作,业务逻辑的处理,视图和业务逻辑之间的对接。

在程序中如果代码不分层的话,那么这个三个切面的实现会耦合在一个类中。为了代码的可维护性、可读性、灵活性(请参看@mcfog的答案),就应该将这些代码按照切面分别写到不同的类中,进而将相同切面的类放到一个包中,这些类和包看起来像在不同的层面上。

如何解耦

mvc是成熟的分层(解耦)方案。

根据第一个问题的回答,要将不同层面的代码放到不同的类(和包)中,那么这些不同层次的代码如何协作?

此问题的其他答案看样子已经具体地,并且图文并茂地回答了这个问题。

Model中的代码负责业务逻辑;
View中的代码负责用户交互;
Controller中的代码负责model和view的对接。

Model View Controller 模型,视图,控制器
模型:数据模型
视图:UI相关元素
控制器:用于把模型和视图联系起来

越简单越好是吧?

M:模型——你如何为数据建模,或者说你的数据用何种结构表示

C:控制器——你如何处理业务逻辑,这个“处理”主要是对应两个端:一端是向模型请求处理需要的数据来源;另一端则是把处理结果用某种方式传递给视图;中间的具体过程就是控制器负责的层面

V:视图——你如何向客户端呈现业务处理的结果以及提供交互

其实说的太简单了也不好,因为有些细节为了简化只能高度概括和抽象,若是没有足够的知识和经验支撑就如同雾里看花。

看了楼上各位的回答,最后觉的:V是给用户看的 C是给用户控制的 M是用户接触不到的 通过C和V对M进行控制?

SO上关于MVC的讨论:What is MVC, really?

简单点说,就是别把 查数据库(Model)展示数据的(View) 代码 搅和在一起,如果还有些业务逻辑要加进来,那就是 控制器(Controller)

C和V是人机界面,C是人机界面的功能部分,V只是呈现形式,把它从图形换成命令程序还能跑,只不过不直观而已。一方面M是供C调度的资源,另一方面M是程序中与人机交互不直接相关的部分,它往往需要C来驱动,但是一经驱动就可以独立运行。很多时候大家谈论MVC时都矮化了M,认为它只是对数据的封装,是静态的,其实这只在逻辑较简单的情况下才成立,这时候似乎可以把逻辑都塞进C中。但是一般情况下,相比于M,C是很轻的,因为它只负责人机交互,而M则是程序的主体部分。

MVC
M--模型,一般是跟数据库打交道的。
V-输出给前端用户的。
C-控制器,用于流程控制,主要是协调M和V的。

顾客到餐厅点菜,顾客点好了,服务员要告诉传菜员,传菜员再告诉后厨。
M--菜
V--服务员(菜单)
C--传菜员

M(菜)应该直接跟后厨打交道,那么后厨就是项目里的Service了。

另外:一些比较low的餐厅,会把服务员和传菜员当作一个人来用。
这就是JAVA项目里的,在JSP里写业务逻辑的作法。

有些更low的餐厅,只有一个老板,这个老板身兼服务员、传菜员、后厨。。
这就是JSP里写数据操作的作法。

所以高级餐厅里,会有各种各样的角色,细分至极。提高效率,提高可维护性。这就是为嘛大餐厅实习生多的原因了。

老板说,想看一下这个月的销售情况。这是一个请求。于是你(C)接受了这个请求,要公司各业务部门(M)提供这个月的所有销售数据,然后把这些数据做一下简单整理交给了老板助理(V)。老板助理用这些整理好的数据按部门做成图表饼图呈交给老板看。

view:处理用户请求
controller:处理前端请求,发起数据库请求
model:处理数据库请求

新手上路,请多包涵

view: 展示页面
controller:处理逻辑
model: 处理数据

mvc的关键,就是路由!!!,路由不懂???就是拆分url地址,剩下的那些,等你写过几个controller的增删该查就渐渐明白了

所以研究mvc,研究路由,就是拆url地址,打完收工!

宣传栏