MVC思想

MVC是一种设计模式(Design pattern),也就是一种解决问题的方法和思路, 是上世纪80年代提出的,到现在已经颇有历史了。 MVC的意义在于指导开发者将数据与表现解耦,提高代码,特别是模型部分代码的复用性。

MVC不仅仅存在于Web设计中,在桌面程序开发中也是一种常见的方法。MVC的出现已经有一段历史了。 记得我最早了解到MVC的时候,是在Microsoft的Visual C++ 中的MFC中。 当时年少无知,以为是MFC中特有的东西。后来随之不断学习,才发现自己的天真。 所以说,学得越多,就越觉得自己无知。越觉得自己无知,就越懂得敬畏和谦逊。 从这个角度讲,同学们,最好不要看不起谦逊的人。

有个这么一个段子,说一天A君在圈内聚会时,朋友介绍了另一个人B君互相认识。 聚会场合嘛,这很正常,也很普遍。于是AB君小聊了一下。按国人的习惯,A君就问了“先生在哪高就?”。 B君只说了句,“谈不上高就,炒炒股。” “哦,原来是炒股的。”A君心想,虽没觉得什么不对,但心理觉得B有点low,只是没说破,也没表现出来。 过后了一段时间,一次偶然机会,发现原来B君是国内某上市公司的二股东,身家过亿。 人家没说慌,确实是炒股的……

话说远了,我们还说正题。MVC是三个单词的缩写:Model, View, Controller。 MVC是一种设计模式,目前几乎所有的Web开发框架都建立在MVC模式之上。 当然,最近几年也出现了一些诸如MVP, MVVM之类的新的设计模式。 但从技术的成熟程度和使用的广泛程度来讲,MVC仍是主流。

Yii是一个Web框架,从Web开发的分工来讲,Yii的开发工作中,承担后端的内容多一些,毕竟主要就是PHP开发。 前端主要是在HTML、JavaScript、CSS上进行开发,然后通过Yii把前端的内容管起来,如通过Assets等。 这一章要讲的MVC,主要是针对后端的。 前端的MVC严格来讲不属于Yii的范畴,这里我们就不作过多介绍。 如果想了解前端的MVC,可以看看Backbone.js Angular.js等前端框架。

MVC的三要素

MVC是模型(Model)、视图(View)、控制器(Controller)3个单词的缩写。 下面我们从这3个方面来讲解MVC中的三个要素。

  • Model是指数据模型,是对客观事物的抽象。 如一篇博客文章,我们可能会以一个Post类来表示,那么,这个Post类就是数据对象。 同时,博客文章还有一些业务逻辑,如发布、回收、评论等,这一般表现为类的方法,这也是model的内容和范畴。 对于Model,主要是数据、业务逻辑和业务规则。相对而言,这是MVC中比较稳定的部分,一般成品后不会改变。 开发初期的最重要任务,主要也是实现Model的部分。这一部分写得好,后面就可以改得少,开发起来就快。
  • View是指视图,也就是呈现给用户的一个界面,是model的具体表现形式,也是收集用户输入的地方。 如你在某个博客上看到的某一篇文章,就是某个Post类的表现形式。 View的目的在于提供与用户交互的界面。换句话说,对于用户而言,只有View是可见的、可操作的。 事实上也是如此,你不会让用户看到Model,更不会让他直接操作Model。 你只会让用户看到你想让他看的内容。 这就是View要做的事,他往往是MVC中变化频繁的部分,也是客户经常要求改来改去的地方。 今天你可能会以一种形式来展示你的博文,明天可能就变成别的表现形式了。
  • Contorller指的是控制器,主要负责与model和view打交道。 换句话说,model和view之间一般不直接打交道,他们老死不相往来。view中不会对model作任何操作, model不会输出任何用于表现的东西,如HTML代码等。这俩甩手不干了,那总得有人来干吧,只能Controller上了。 Contorller用于决定使用哪些Model,对Model执行什么操作,为视图准备哪些数据,是MVC中沟通的桥梁。

对于MVC中三者的划分并没有十分明晰的定义和界线。MVC设计模式只是一种指导思想, 让你按照model, view, controller三个方面来描述你的应用,并通过三者的交互,使应用功能得以正常运转。

其中,View的部分比较明确,就是负责显示嘛。一切与显示界面无关的东西,都不应该出现在View里面。 因此,View中一般不会出现复杂的判断语句,不会出现复杂的运算过程。 对于PHP的Web应用而言,毫无疑问,HTML是View中的主要内容。这是关于View的几个原则:

  • 负责显示界面,以HTML为主;
  • 一般没有复杂的判断语句或运算过程,可以有简单的循环语句、格式化语句。 比如,一般博客首页的文章列表,就是一种循环结构;
  • 从不调用Model的写方法。也就是说,View只从Model获取数据,而不直接改写Model,所以我们说他们老死不相往来。
  • 一般没有任何准备数据的代码,如查询数据库、组合成一定格式的字符串等。 这些一般放在Controller里面,并以变量的形式传给视图。 也就是说,视图里面要用到的数据,都是拿来就能直接用的变量。

对于Model而言,最主要就是保存事物的信息,表征事物的行为和对他可以进行的操作。 比如,Post类必然有一个用于保存博客文章标题的title属性,必然有一个删除的操作,这都是Model的内容。 以下是关于Model的几个原则:

  • 数据、行为、方法是Model的主要内容;
  • 实际工作中,Model是MVC中代码量最大,逻辑最复杂的地方,因为关于应用的大量的业务逻辑也要在这里面表示。
  • Model所提供的数据都是原始数据。也就是说,不带有任何表现层的代码。 比如,一般不会在输出的数据中添加HTML标签,这是View的工作。 但是Model可以提供有结构的数据,数组结构、队列结构、乃至其他Model等。 这个结构并非是表现层的格式,而是数据在内存中的表现。
  • 与输出不同,Model的输入数据,可以是带有表现格式的数据。 如将一篇文章保存到Post里面,内容中必然包含各种HTML标签。 因此,Model一般要对输入数据作过滤、验证和规范化等预处理。 特别是对于需要保存进数据库的,一定要对所有的输入数据作预处理。 这些预处理,有的其实是业务逻辑。比如只有主编才可以删除文章,这一验证规则既也是业务逻辑,也是权限控制。 而有些预处理,则不属于业务逻辑,比如,文章标题前后的空格应去除。
  • 注意与Controller区分开。Model是处理业务方面的逻辑,Controller只是简单的协调Model和View之间的关系, 只要是与业务有关的,就该放在Model里面。好的设计,应当是胖Model,瘦Controller。

对于Controller,主要是响应用户请求,决定使用什么视图,需要准备什么数据用来显示。 以下是有关Controller的设计原则:

  • 用于处理用户请求。 因此,对于reqeust的访问代码应该放在Controller里面,比如 $_GET $_POST等。 但仅限于获取用户请求数据,不应该对数据有任何操作或预处理,这些工作应该交由Models来完成。
  • 调用Models的读方法,获取数据,直接传递给视图,供显示。 当涉及到多个Model时,有关的逻辑应当交给Model来完成。
  • 调用Models的类方法,对Models进行写操作。
  • 调用视图渲染函数等,形成对用户Reqeust的Response。

Model设计参考

在MVC中,Model排第一,是有一定暗示的。一是Model是整个架构中,代码量最大,复用程度最高, 也是最体现程序员设计功力的地方。 二是View和Controller相对于Model而言,在实际开发中,复用程度不高,逻辑复杂程度较低。 可以说,Model设计得好,整个MVC就好,应用开发起就顺。

因此,这一节将以Model为核心,来讲MVC的设计。 实话说,MVC尽管提出了Model View Controller的划分思想,但到了具体实操中,并不是很好把握的。 下面介绍的设计参考,也仅仅是个人在实际项目中的一些体会和想法,仅作参考。 在具体设计中,可以后把握这么几点:

Model应当集中整个应用的数据和业务逻辑

应用当中涉及到的所有业务对象都应尽可能抽像成Model。 如,博客系统当中,文章要抽象成Post,评论要抽象成Comment。 而相关的业务逻辑,如发布新文章可以用 Post::create() ,删除评论可以用 Comment::delete() 。 这样子整个应用就显得很清晰明了。

基础Model应当尽可能细化

在一个应用中,特别是对于大型复杂应用,Model间关系可能比较复杂。在构造应用时,特别是基础Model时, 要从足够小的粒度来设计。 此时,就要考虑采取继承、封装等措施了。 比如,一个博客文章Post,一般包含了若干标签,在页上一般写在作者、日期等Post字段的旁边。 从逻辑上来看,把标签作为Post的一个属性,是说得通的。 但是如果把标签作为一个属性像标题、正文等字段一样依附于Post。那么在有的功能上,实现起来是有难度的。 比如,客户要求,当一个Post含有标签 “yii, model” 时,可以点击 “yii” , 然后系统列出所有具标签中含有 “yii” 的文章。

为了实现这个功能,正确的设计是单独将标签抽象成Tag。这样,Post和Tag是多对多的关系, 即一个Post有多个Tag,一个Tag也对应多个Post。这个多对多关系可以通过一张数据表 tbl_post_tag 来表示。 接下来,为Post增加 Post::getTags() 方法,并通过 tbl_post_tag 表来查询当前Post的所有标签。 同时,为Tag增加 Tag::getPosts() 方法,也通过 tbl_post_tag 表来查询当前Tag对应的文章。 这样,就具备了实现客户要求的新功能的基础。

因此,在Model设计上,要以尽量小的粒度进行设计。一般而言,粒度越小,复用的可能性就越高。

有的读者可能会问了,既然要求粒度尽可能地小,那么,Post是不是也应当再细化,把段落抽象为Model? 是否有这个必要,看客户需求。一般情况确实没有这必要,如果这么做,那是不是再以句子为单位进行抽象? 但如果客户要求这个博客系统的评论是针对段落进行的评论的, 要将评论显示在对应的段落旁边,甚至显示每个段落评论人次等功能。那么就需要把段落抽象成Model了。

分层次设计Model

从设计流程上,数据库结构设计与Model的设计是紧密相关的。先有数据库结构设计,后有Model设计。 在设计数据库结构的时候,也是在设计Model。 一般而言,最单元、粒度最小的Model就是根据每个数据库表所生成的Model,这往往是个Active Record。

比如标签的问题,在数据库存储过程中,Post和Tag是分开存的,而且这两个表的字段,没有冗余。 tbl_post_tag 表也只记录他们的ID,没有实质内容。

在获取数据渲染视图,向用户展现时,这两个Model及他们的字段,是完全够用,且没有冗余的。

那么,能不能说 Post 和 Tag 这两个Model是够用的呢?显然还不够。

当用户在创建文章、修改文章、审核文章时,需要采用一个表单来显示来收集用户输入。 其中,对于标签的采集,一般是一个长条的文本框,让用户一次性输入多个标签,并以 , 等进行分隔的。

但是,这个文本框没有一个字段与之进行对应。我们也没办法对这个字段的用户输入进行任何的验证、预处理。

因此,Post的功能是不够用的。不够用怎么办?那就加吧。但直接在 Post 里面加个 public $tagString 并不好。 毕竟只是在使用表单时,才会有这个问题,其他场合,这个字段是没用的。

这种情况下,一般使用继承:

1
2
3
4
5
6

public class PostForm extends Post
{
    public $tagString;

    ... ...
}

这样,当控制器发现用户在创建、修改、审核文章时,可以使用 PostForm Model来渲染视图了, 而其他场合则仍使用Post。这样就在需要时,增加了一个 tagString 的字段用于收集用户输入的标签。

在具体设计过程中,由于Model本身就会包含很多代码,因此,要多使用这继承等手段,把代码组织好。

仔细为Model方法命名

由于Model的代码量比较大,又集中了大量的逻辑,因此,会在一个Model中有大量的方法。仍然以Post为例, 会涉及到创建、审核、发布、回收等流程,相关的方法比较多,在命名上要用心。 可能会涉及到的、名字又比较接近的方法就有:

  • getPrevPost(),前一篇文章,用于导航
  • getNextPost(),下一篇文章,用于导航
  • getRelatedPosts($n = 10),获取相关的N篇文章,用于相关文章推荐列表
  • getPostsOfAuthor($n = 10),获取同一作者的N篇相关文章,用于作者文章列表
  • getLatestPosts($n = 10),最新的N篇文章,静态方法,用于文章列表或RSS输出
  • getHotestPosts($n = 10),最热门的N篇文章,静态方法,用于热门文章列表
  • getPublishPosts($n = -1),获取已经发布的N篇文章,静态方法,用于文章列表
  • getDraftPosts($n = -1),获取未发布的N篇文章,静态方法,用于作者页面

这里只是一些获取其他Post的方法,命名比较合理,一看就知道意思。 而且全部写成getter的形式,可以使用读取属性的方式进行访问。

不单单是在Model方法的命名上要用心, 在变量名、类名、方法名等的命名上,也要养成习惯,形成规律。 不要图一时之快,胡乱起名。否则,出来混,迟早要还的。

MVC与前后端的配合

从MVC的起源来讲,是从桌面应用的开发中发展起来的。从本质来讲,这是一种解决问题的思路和办法。 从实践来讲,这是一种久经考验的有效方式。但是如开头我们讲的,Yii更多的是侧重于后端。 对于Web应用而言,包含Yii在内的许多Web开发框架,都是没有办法知道用户的操作,如鼠标、键盘等操作的。 Web应用想要了解用户的操作,只能依靠用户发送Request。 而对于鼠标、键盘等的响应,只能依靠前端技术,如JavaScript等来实现。

再加上这几年来Web浏览器的功能日臻强大。因此,Web应用开发出现了一个新的发展苗头,就是功能从后端往前端转移。

在前端,通过JavaScript捕获用户操作,进行相应处理。 或是发送回后端获取响应后处理,如通过ajax请求后端数据,实现无刷新的局部页面更新,向用户进行反馈; 或直接在前端由浏览器进行处理,如使用backbone.js、Angular.js等前端框架的数据绑定功能等。 这些都使得Web应用表现得越来越像桌面应用。

后端MVC也在为前后端的发展而改变。 Controller的功能更多的变成了识别是ajax请求还是普通请求, 并根据请求的不同采取相应的视图渲染方式。对于普通请求,正常渲染视图,输出HTML。 对于ajax请求,则返回局部渲染视图,输出HTML片段。有的甚至输出XML或者JSON。 唯一在大潮流中,巍然不动的,还是我们的大Model。

MVC是一种设计模式(Design pattern),也就是一种解决问题的方法和思路, 是上世纪80年代提出的,到现在已经颇有历史了。 MVC的意义在于指导开发者将数据与表现解耦,提高代码,特别是模型部分代码的复用性。

MVC不仅仅存在于Web设计中,在桌面程序开发中也是一种常见的方法。MVC的出现已经有一段历史了。 记得我最早了解到MVC的时候,是在Microsoft的Visual C++ 中的MFC中。 当时年少无知,以为是MFC中特有的东西。后来随之不断学习,才发现自己的天真。 所以说,学得越多,就越觉得自己无知。越觉得自己无知,就越懂得敬畏和谦逊。 从这个角度讲,同学们,最好不要看不起谦逊的人。

有个这么一个段子,说一天A君在圈内聚会时,朋友介绍了另一个人B君互相认识。 聚会场合嘛,这很正常,也很普遍。于是AB君小聊了一下。按国人的习惯,A君就问了“先生在哪高就?”。 B君只说了句,“谈不上高就,炒炒股。” “哦,原来是炒股的。”A君心想,虽没觉得什么不对,但心理觉得B有点low,只是没说破,也没表现出来。 过后了一段时间,一次偶然机会,发现原来B君是国内某上市公司的二股东,身家过亿。 人家没说慌,确实是炒股的……

话说远了,我们还说正题。MVC是三个单词的缩写:Model, View, Controller。 MVC是一种设计模式,目前几乎所有的Web开发框架都建立在MVC模式之上。 当然,最近几年也出现了一些诸如MVP, MVVM之类的新的设计模式。 但从技术的成熟程度和使用的广泛程度来讲,MVC仍是主流。

Yii是一个Web框架,从Web开发的分工来讲,Yii的开发工作中,承担后端的内容多一些,毕竟主要就是PHP开发。 前端主要是在HTML、JavaScript、CSS上进行开发,然后通过Yii把前端的内容管起来,如通过Assets等。 这一章要讲的MVC,主要是针对后端的。 前端的MVC严格来讲不属于Yii的范畴,这里我们就不作过多介绍。 如果想了解前端的MVC,可以看看Backbone.js Angular.js等前端框架。

MVC的三要素

MVC是模型(Model)、视图(View)、控制器(Controller)3个单词的缩写。 下面我们从这3个方面来讲解MVC中的三个要素。

  • Model是指数据模型,是对客观事物的抽象。 如一篇博客文章,我们可能会以一个Post类来表示,那么,这个Post类就是数据对象。 同时,博客文章还有一些业务逻辑,如发布、回收、评论等,这一般表现为类的方法,这也是model的内容和范畴。 对于Model,主要是数据、业务逻辑和业务规则。相对而言,这是MVC中比较稳定的部分,一般成品后不会改变。 开发初期的最重要任务,主要也是实现Model的部分。这一部分写得好,后面就可以改得少,开发起来就快。
  • View是指视图,也就是呈现给用户的一个界面,是model的具体表现形式,也是收集用户输入的地方。 如你在某个博客上看到的某一篇文章,就是某个Post类的表现形式。 View的目的在于提供与用户交互的界面。换句话说,对于用户而言,只有View是可见的、可操作的。 事实上也是如此,你不会让用户看到Model,更不会让他直接操作Model。 你只会让用户看到你想让他看的内容。 这就是View要做的事,他往往是MVC中变化频繁的部分,也是客户经常要求改来改去的地方。 今天你可能会以一种形式来展示你的博文,明天可能就变成别的表现形式了。
  • Contorller指的是控制器,主要负责与model和view打交道。 换句话说,model和view之间一般不直接打交道,他们老死不相往来。view中不会对model作任何操作, model不会输出任何用于表现的东西,如HTML代码等。这俩甩手不干了,那总得有人来干吧,只能Controller上了。 Contorller用于决定使用哪些Model,对Model执行什么操作,为视图准备哪些数据,是MVC中沟通的桥梁。

对于MVC中三者的划分并没有十分明晰的定义和界线。MVC设计模式只是一种指导思想, 让你按照model, view, controller三个方面来描述你的应用,并通过三者的交互,使应用功能得以正常运转。

其中,View的部分比较明确,就是负责显示嘛。一切与显示界面无关的东西,都不应该出现在View里面。 因此,View中一般不会出现复杂的判断语句,不会出现复杂的运算过程。 对于PHP的Web应用而言,毫无疑问,HTML是View中的主要内容。这是关于View的几个原则:

  • 负责显示界面,以HTML为主;
  • 一般没有复杂的判断语句或运算过程,可以有简单的循环语句、格式化语句。 比如,一般博客首页的文章列表,就是一种循环结构;
  • 从不调用Model的写方法。也就是说,View只从Model获取数据,而不直接改写Model,所以我们说他们老死不相往来。
  • 一般没有任何准备数据的代码,如查询数据库、组合成一定格式的字符串等。 这些一般放在Controller里面,并以变量的形式传给视图。 也就是说,视图里面要用到的数据,都是拿来就能直接用的变量。

对于Model而言,最主要就是保存事物的信息,表征事物的行为和对他可以进行的操作。 比如,Post类必然有一个用于保存博客文章标题的title属性,必然有一个删除的操作,这都是Model的内容。 以下是关于Model的几个原则:

  • 数据、行为、方法是Model的主要内容;
  • 实际工作中,Model是MVC中代码量最大,逻辑最复杂的地方,因为关于应用的大量的业务逻辑也要在这里面表示。
  • Model所提供的数据都是原始数据。也就是说,不带有任何表现层的代码。 比如,一般不会在输出的数据中添加HTML标签,这是View的工作。 但是Model可以提供有结构的数据,数组结构、队列结构、乃至其他Model等。 这个结构并非是表现层的格式,而是数据在内存中的表现。
  • 与输出不同,Model的输入数据,可以是带有表现格式的数据。 如将一篇文章保存到Post里面,内容中必然包含各种HTML标签。 因此,Model一般要对输入数据作过滤、验证和规范化等预处理。 特别是对于需要保存进数据库的,一定要对所有的输入数据作预处理。 这些预处理,有的其实是业务逻辑。比如只有主编才可以删除文章,这一验证规则既也是业务逻辑,也是权限控制。 而有些预处理,则不属于业务逻辑,比如,文章标题前后的空格应去除。
  • 注意与Controller区分开。Model是处理业务方面的逻辑,Controller只是简单的协调Model和View之间的关系, 只要是与业务有关的,就该放在Model里面。好的设计,应当是胖Model,瘦Controller。

对于Controller,主要是响应用户请求,决定使用什么视图,需要准备什么数据用来显示。 以下是有关Controller的设计原则:

  • 用于处理用户请求。 因此,对于reqeust的访问代码应该放在Controller里面,比如 $_GET $_POST等。 但仅限于获取用户请求数据,不应该对数据有任何操作或预处理,这些工作应该交由Models来完成。
  • 调用Models的读方法,获取数据,直接传递给视图,供显示。 当涉及到多个Model时,有关的逻辑应当交给Model来完成。
  • 调用Models的类方法,对Models进行写操作。
  • 调用视图渲染函数等,形成对用户Reqeust的Response。

Model设计参考

在MVC中,Model排第一,是有一定暗示的。一是Model是整个架构中,代码量最大,复用程度最高, 也是最体现程序员设计功力的地方。 二是View和Controller相对于Model而言,在实际开发中,复用程度不高,逻辑复杂程度较低。 可以说,Model设计得好,整个MVC就好,应用开发起就顺。

因此,这一节将以Model为核心,来讲MVC的设计。 实话说,MVC尽管提出了Model View Controller的划分思想,但到了具体实操中,并不是很好把握的。 下面介绍的设计参考,也仅仅是个人在实际项目中的一些体会和想法,仅作参考。 在具体设计中,可以后把握这么几点:

Model应当集中整个应用的数据和业务逻辑

应用当中涉及到的所有业务对象都应尽可能抽像成Model。 如,博客系统当中,文章要抽象成Post,评论要抽象成Comment。 而相关的业务逻辑,如发布新文章可以用 Post::create() ,删除评论可以用 Comment::delete() 。 这样子整个应用就显得很清晰明了。

基础Model应当尽可能细化

在一个应用中,特别是对于大型复杂应用,Model间关系可能比较复杂。在构造应用时,特别是基础Model时, 要从足够小的粒度来设计。 此时,就要考虑采取继承、封装等措施了。 比如,一个博客文章Post,一般包含了若干标签,在页上一般写在作者、日期等Post字段的旁边。 从逻辑上来看,把标签作为Post的一个属性,是说得通的。 但是如果把标签作为一个属性像标题、正文等字段一样依附于Post。那么在有的功能上,实现起来是有难度的。 比如,客户要求,当一个Post含有标签 “yii, model” 时,可以点击 “yii” , 然后系统列出所有具标签中含有 “yii” 的文章。

为了实现这个功能,正确的设计是单独将标签抽象成Tag。这样,Post和Tag是多对多的关系, 即一个Post有多个Tag,一个Tag也对应多个Post。这个多对多关系可以通过一张数据表 tbl_post_tag 来表示。 接下来,为Post增加 Post::getTags() 方法,并通过 tbl_post_tag 表来查询当前Post的所有标签。 同时,为Tag增加 Tag::getPosts() 方法,也通过 tbl_post_tag 表来查询当前Tag对应的文章。 这样,就具备了实现客户要求的新功能的基础。

因此,在Model设计上,要以尽量小的粒度进行设计。一般而言,粒度越小,复用的可能性就越高。

有的读者可能会问了,既然要求粒度尽可能地小,那么,Post是不是也应当再细化,把段落抽象为Model? 是否有这个必要,看客户需求。一般情况确实没有这必要,如果这么做,那是不是再以句子为单位进行抽象? 但如果客户要求这个博客系统的评论是针对段落进行的评论的, 要将评论显示在对应的段落旁边,甚至显示每个段落评论人次等功能。那么就需要把段落抽象成Model了。

分层次设计Model

从设计流程上,数据库结构设计与Model的设计是紧密相关的。先有数据库结构设计,后有Model设计。 在设计数据库结构的时候,也是在设计Model。 一般而言,最单元、粒度最小的Model就是根据每个数据库表所生成的Model,这往往是个Active Record。

比如标签的问题,在数据库存储过程中,Post和Tag是分开存的,而且这两个表的字段,没有冗余。 tbl_post_tag 表也只记录他们的ID,没有实质内容。

在获取数据渲染视图,向用户展现时,这两个Model及他们的字段,是完全够用,且没有冗余的。

那么,能不能说 Post 和 Tag 这两个Model是够用的呢?显然还不够。

当用户在创建文章、修改文章、审核文章时,需要采用一个表单来显示来收集用户输入。 其中,对于标签的采集,一般是一个长条的文本框,让用户一次性输入多个标签,并以 , 等进行分隔的。

但是,这个文本框没有一个字段与之进行对应。我们也没办法对这个字段的用户输入进行任何的验证、预处理。

因此,Post的功能是不够用的。不够用怎么办?那就加吧。但直接在 Post 里面加个 public $tagString 并不好。 毕竟只是在使用表单时,才会有这个问题,其他场合,这个字段是没用的。

这种情况下,一般使用继承:

1
2
3
4
5
6

public class PostForm extends Post
{
    public $tagString;

    ... ...
}

这样,当控制器发现用户在创建、修改、审核文章时,可以使用 PostForm Model来渲染视图了, 而其他场合则仍使用Post。这样就在需要时,增加了一个 tagString 的字段用于收集用户输入的标签。

在具体设计过程中,由于Model本身就会包含很多代码,因此,要多使用这继承等手段,把代码组织好。

仔细为Model方法命名

由于Model的代码量比较大,又集中了大量的逻辑,因此,会在一个Model中有大量的方法。仍然以Post为例, 会涉及到创建、审核、发布、回收等流程,相关的方法比较多,在命名上要用心。 可能会涉及到的、名字又比较接近的方法就有:

  • getPrevPost(),前一篇文章,用于导航
  • getNextPost(),下一篇文章,用于导航
  • getRelatedPosts($n = 10),获取相关的N篇文章,用于相关文章推荐列表
  • getPostsOfAuthor($n = 10),获取同一作者的N篇相关文章,用于作者文章列表
  • getLatestPosts($n = 10),最新的N篇文章,静态方法,用于文章列表或RSS输出
  • getHotestPosts($n = 10),最热门的N篇文章,静态方法,用于热门文章列表
  • getPublishPosts($n = -1),获取已经发布的N篇文章,静态方法,用于文章列表
  • getDraftPosts($n = -1),获取未发布的N篇文章,静态方法,用于作者页面

这里只是一些获取其他Post的方法,命名比较合理,一看就知道意思。 而且全部写成getter的形式,可以使用读取属性的方式进行访问。

不单单是在Model方法的命名上要用心, 在变量名、类名、方法名等的命名上,也要养成习惯,形成规律。 不要图一时之快,胡乱起名。否则,出来混,迟早要还的。

MVC与前后端的配合

从MVC的起源来讲,是从桌面应用的开发中发展起来的。从本质来讲,这是一种解决问题的思路和办法。 从实践来讲,这是一种久经考验的有效方式。但是如开头我们讲的,Yii更多的是侧重于后端。 对于Web应用而言,包含Yii在内的许多Web开发框架,都是没有办法知道用户的操作,如鼠标、键盘等操作的。 Web应用想要了解用户的操作,只能依靠用户发送Request。 而对于鼠标、键盘等的响应,只能依靠前端技术,如JavaScript等来实现。

再加上这几年来Web浏览器的功能日臻强大。因此,Web应用开发出现了一个新的发展苗头,就是功能从后端往前端转移。

在前端,通过JavaScript捕获用户操作,进行相应处理。 或是发送回后端获取响应后处理,如通过ajax请求后端数据,实现无刷新的局部页面更新,向用户进行反馈; 或直接在前端由浏览器进行处理,如使用backbone.js、Angular.js等前端框架的数据绑定功能等。 这些都使得Web应用表现得越来越像桌面应用。

后端MVC也在为前后端的发展而改变。 Controller的功能更多的变成了识别是ajax请求还是普通请求, 并根据请求的不同采取相应的视图渲染方式。对于普通请求,正常渲染视图,输出HTML。 对于ajax请求,则返回局部渲染视图,输出HTML片段。有的甚至输出XML或者JSON。 唯一在大潮流中,巍然不动的,还是我们的大Model。

时间: 2024-10-24 10:21:56

MVC思想的相关文章

【UI插件】简单的日历插件(下)—— 学习MVC思想

前言 我们上次写了一个简单的日历插件,但是只是一个半成品,而且做完后发现一些问题,于是我们今天尝试来解决这些问题 PS:距离上次貌似很久了 上次,我们大概遇到哪些问题呢: ① 既然想做一套UI库,那么就应该考虑其它UI库的接入问题 这个意思就是,我们的系统中所有UI插件应该有一些统一行为,我们如果希望统一为所有的插件加一点什么东西,需要有位置可加 这个意味着,可能我们所有的插件需要继承至一个抽象的UI类,并且该类提供了通用的几个事件点 ② 上次做的日历插件虽然说是简单,其耦合还是比较严重的(其实

Struts2的MVC思想

 MVC思想概述 MVC思想将一个应用分成三个基本部分:Model(模型).View(视图).Controller(控制器),这三个部分以最少的耦合协同工作,从而提高应用的可扩展性及可维护性. 在经典的MVC模型中,事件由控制器处理,控制器根据事件的类型改变模型或视图,反之亦然.具体地说,每个模型对应一系列的视图列表,这种对应关系通常采用注册来完成,即:把多个视图(View)注册到同一个模型(Model),当模型发生改变时,模型向所有注册过的视图发送通知,接下来,视图从对应的模型中获得信息,

【Servlet】根据MVC思想设计用户登陆、用户注册、修改密码系统

MVC不是一种像C.JAVA的编程语言,也不是一种像Ajax,Servlet的技术,只是一种如同面向对象一样编程思想.近年来MVC一直很火,赞者批者有之,然后大篇幅的文章很多,可是简明扼要的简单MVC的例子几乎没有.在JSP领域一直向鼓风机地猛吹SSH如何如何地好,一直怒批JSP,Servlet等如何如何差.其实使用JSP+Servlet同样可以利用MVC思想来完成一个系统.下面用一个烂得不能再烂的例子,你步入网页编程必须学会的东西,登陆.注册.修改密码系统,来说明这种编程思想. 一.基本目标

深入理解Spring MVC 思想

原文:http://www.cnblogs.com/baiduligang/p/4247164.html 深入理解Spring MVC 思想 目录  一.前言二.spring mvc 核心类与接口三.spring mvc 核心流程图 四.spring mvc DispatcherServlet说明 五.spring mvc 父子上下文的说明 六.springMVC-mvc.xml 配置文件片段讲解 七.spring mvc 如何访问到静态的文件,如jpg,js,css 八.spring mvc 

简洁的MVC思想框架——Nancy(环境配置与Get操作)

Nancy官网——https://github.com/NancyFx/Nancy 概述:Nancy是一个开源的Web轻型框架内核符合MVC思想,有开发方便,路由简单的特点,而且功能齐全 起步:Hellow World 一.建立Asp.Net空Web应用程序 二.使用NuGet添加Nancy包的引用 安装三个Nancy应用包——Nancy.Hosting.Aspnet;Nancy;Nancy.Viewengines.Razor; 至此,环境已经搭好,上代码(注:必须在项目根目录建立Views文件

基于servlet,jsp,来进行MVC思想的剖析 第一部分

这个简单的MVC遵循下图为整体思路 解读MVC思想(jsp和servlet实现),其实MVC(Model,view,controllor)思想就是把代码分离开来各自分工合作,首先让我们结合实例来进行分析,看我们这个项目下会有一个FrontControllor.java 这个是用来进行处理请求的一个前段控制期用来处理一个前端发来的请求,让我们先来看一下前端控制器的内部实现原理吧! 继承了HttpServlet类并且覆盖了init()方法,并且通过super.init()可以知道,此方法覆盖相当于追

php学习之bbs论坛项目-web架构和MVC思想

--显示和逻辑相分离-- 将功能强制地分成两个部分:1.负责显示的HTML部分 2.负责业务逻辑处理的PHP代码 HTML主要负责展示的部分,其中可变的数据是用动态脚本PHP来填充. 这样的混编文件一般叫作模板文件.因为用户不能直接请求模板文件,所以要通过apache分布式配置文件来隐藏它们. 在apache主配置文件中(httpd-vhosts.conf),配置权限时再多添加这样一行代码: Allowoverride all 接着,再在模板文件中创建.htaccess文件,写入如下代码即可.

javaBean和mvc思想

JavaBean,  咖啡豆. JavaBean是一种开发规范,可以说是一种技术. JavaBean就是一个普通的java类.只有符合以下规定才能称之为javabean: 1)必须提供无参数的构造方法 2)类中属性都必须私有化(private) 3)该类提供公开的getter 和 setter方法 JavaBean的作用: 用于封装数据,保存数据. 访问javabean只能使用getter和setter方法 JavaBean的使用场景: 1)项目中用到实体对象(entity)符合javabean

【Struts2+Hibernate4】按照MVC思想使用Hibernate查询数据库,并且在前台使用OGNL表达式输出

本文将介绍Struts2与Hibernate的整合,两东西的整合并不需要用到Spring,完全可以各司其职,Struts2完成Java文件与Jsp页面交互,Hibernate完成数据库到Java文件的交互. 一.基本目标 还是那张在Mysql中已经用烂的Testtable表. 在index.jsp点击查询之后,能够把这张表的所有内容输出出来.而且表格是梅花间竹的不同颜色.当然这个例子已经很多书籍上说过了. 目录结构如下,严格按照MVC思想. 二.基本准备 1.这里就不再多说了,在Eclipse

java web mvc思想介绍

1.首先简单介绍一下什么是MVC思想. 在百度百科里面对MVC的说明,MVC全名是Model View Controller,是模型(model)-视图(view)-控制器(controller)的缩写.那么在JAVA的web开发中,MVC分别是对应于:显示页面(视图).数据对象(模型).业务处理(控制器). 简单举个例子来说,在学生信息管理系统里,登陆界面就是一个视图,而登陆完成后,进行用户名和密码判断并跳转相应的页面,就是控制器,而保存用户名和密码的对象,就是模型.三者的关系就是这样.我们下