1. 首先通俗地说说我对MVC的理解:

Model是负责干活的,它干的活主要是从数据库中获取需要的数据以及对获取的数据按照业务逻辑进行加工处理,至于为什么要干某件活,何时干某件活它一概不管,而这正是Controller的职责,Controller像个餐馆招待,接到食客的需求,马上传达给厨房,Model就是大厨。View负责最终把菜端上桌,摆在合适的位置上。比如说客人来了要了个糖醋鲤鱼,接待客人的是Controller,它会通知Model做一道糖醋鲤鱼,做好之后它又会招呼View把菜端上桌,View知道这是主菜,它会把它摆在桌子中央。MVC的最大优势就在于把数据处理流程控制UI显示较好地分离开来,便于程序的开发和维护。

2.下面看具体实现。
这个小程序一共包含6个文件,其中index.php是程序入口、post.htm是留言表单

在lib文件夹里Model、View 、Controller三个文件分别实现MVC,DataAccess是一个简单的数据库访问类

(1)DataAccess

 <?php
/**
* 一个用来访问MySQL的类
* 仅仅实现演示所需的基本功能,没有容错等
* 代码未作修改,只是把注释翻译一下,加了点自己的体会
*/
class DataAccess { var $link_id; //用于存储数据库连接 var $query_id; //用于存储查询源
//! 构造函数.
/**
* 创建一个新的DataAccess对象
* @param $host 数据库服务器名称
* @param $user 数据库服务器用户名
* @param $pass 密码
* @param $db 数据库名称
*/
function __construct($host,$user,$pass,$db) {
$this->link_id=mysql_pconnect($host,$user,$pass); //连接数据库服务器
mysql_select_db($db,$this->link_id); //选择所需数据库 mysql_query("set names utf8;");
}
//! 执行SQL语句
/**
* 执行SQL语句,获取一个查询源并存储在数据成员$query中
* @param $sql 被执行的SQL语句字符串
* @return void
*/
function query($sql) {
$this->query_id=mysql_unbuffered_query($sql,$this->link_id); // Perform query here
if ($this->query_id) return true;
else return false;
}
//! 获取结果集
/**
* 以数组形式返回查询结果的所有记录
* @return mixed
*/
function fetchRows($sql) {
$this->query($sql);
$arr=array();
$i=0;
while( $row=mysql_fetch_array($this->query_id,MYSQL_ASSOC) )
//MYSQL_ASSOC参数决定了数组键名用字段名表示
{ $arr[$i]=$row;
$i++;
}
return $arr; }
}
?>

(2)下面我们要介绍Model类,这个类很简单,里面的函数一看就知道,是针对各种数据的操作,它是通过DataAccess访问数据库

Model

 <?php

 //! Model类
/**
* 它的主要部分是对应于留言本各种数据操作的函数
* 如:留言数据的显示、插入、删除等
*/
class Model { var $dao; //DataAccess类的一个实例(对象)
//! 构造函数
/**
* 构造一个新的Model对象
* @param $dao是一个DataAccess对象
* 该参数以地址传递(&$dao)的形式传给Model
* 并保存在Model的成员变量$this->dao中
* Model通过调用$this->dao的fetch方法执行所需的SQL语句
*/
function __construct(&$dao) {
$this->dao=$dao;
}
function listNote() { //获取全部留言
$notes=$this->dao->fetchRows("SELECT * FROM note ORDER BY timedate DESC"); return $notes; } function postNote() { //插入一条新留言 $name=$_POST['username'];
$email=$_POST['email'];
$content=$_POST['content'];
$timedate=time()+8*3600;
$sql="INSERT INTO note (name, email, content, timedate) VALUES
('".$name."', '".$email."', '".$content."', '".$timedate."' )";
//echo $sql; //对于较复杂的合成SQL语句,<br />
//调试时用echo输出一下看看是否正确是一种常用的调试技巧
if ($this->dao->query($sql)) return true;
else return false;
} function deleteNote() { //删除一条留言,$id是该条留言的id
$sql="DELETE FROM note WHERE id=".$_GET['id'];
if ($this->dao->query($sql)) return true;
else return false;
} }
?>

(3)看完这两个类之后你可能会发现这与以前我们写程序差不多,的确现在还闻不到MVC的味道,如果你不懂MVC,在这两个类的基础上你完全可以开始写你以前的程序了。例如要显示全部留言,只需要写入下代码:

 <?php
require_once('lib/DataAccess.php');
require_once('lib/Model.php'); $dao=& new DataAccess ('localhost','root','password','test');
$model=& new Model($dao);
$notes=$model->listNote();
……
?>

  很亲切吧,呵呵。
    有了这个"感情基础"你就不会对MVC望而生畏了,下面我们就要上今天的主菜了,那就是"Controller"闪亮登场!
    先大体浏览一下主要结构,它包括一个Controller类以及派生出的三个子类listController对应显示留言功能postController对应发表留言功能以及deleteController对应删除留言功能)。

Controller:

 <?php
//! Controller
/**
* 控制器将$_GET['action']中不同的参数(list、post、delete)
* 对应于完成该功能控制的相应子类
*/
class Controller {
var $model; // Model 对象
var $view; // View 对象
//! 构造函数
/**
* 构造一个Model对象存储于成员变量$this->model;
*/
function __construct (& $dao) {
$this->model=& new Model($dao);
} function getView() { //获取View函数
//返回视图对象view
//对应特定功能的Controller子类生成对应的View子类的对象
//通过该函数返回给外部调用者
return $this->view;
} }
//用于控制显示留言列表的子类
class listController extends Controller{ //extends表示继承
function __construct (& $dao) {
parent::__construct($dao); //继承其父类的构造函数
//该行的含义可以简单理解为:
//将其父类的构造函数代码复制过来
$notes=$this->model->listNote();
$this->view=& new listView($notes);
//创建相应的View子类的对象来完成显示 }
}
//用于控制添加留言的子类
class postController extends Controller{
function __construct (& $dao) {
parent::__construct($dao);
if ($this->model->postNote()) $success=1;
else $success=0;
$this->view=& new postView($success);
}
}
//用于控制删除留言的子类
class deleteController extends Controller{
function __construct (& $dao) {
parent::__construct($dao);
if ($this->model->deleteNote()) $success=1;
else $success=0;
$this->view=& new deleteView($success);
}
} ?>

(4)大体浏览之后,你一定打算开始仔细研究它了吧,别急,为了心中有数,我们先从宏观着眼,先看看总入口index.php是如何调用Controller的

 <html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>PHP MVC留言板</title>
</head>
<body leftmargin="50px">
<a href="notebook.htm">添加新留言</a><br>
<p>
<?php
//!index.php 总入口
/**
* index.php的调用形式为:
* 显示所有留言:index.php?action=list
* 添加留言 :index.php?action=post
* 删除留言 :index.php?action=delete&id=x
*/
require_once('lib/DataAccess.php');
require_once('lib/Model.php');
require_once('lib/View.php');
require_once('lib/Controller.php');
//创建DataAccess对象(请根据你的需要修改参数值)
$dao=& new DataAccess ('localhost','root','your password here','notebook');
//根据$_GET["action"]取值的不同调用不同的控制器子类
$action=$_GET["action"];
switch ($action)
{
case "post":
$controller=& new postController($dao); break;
case "list":
$controller=& new listController($dao); break;
case "delete":
$controller=& new deleteController($dao); break;
default:
$controller=& new listController($dao); break; //默认为显示留言 }
$view=$controller->getView(); //获取视图对象
$view->display(); //输出HTML
?>
</body>
</html>

看过index.php之后你就更清楚了吧,原来功能是通过$_GET[“action”]指定的,由一个switch结构分发,不同的功能对应不同的Controller子类。现在可以滚上去(滚动页面上去的简称,绝非不洁用语^_^)仔细看看这个Controller代码了。注释应该很细了,不懂的地方就去看看PHP5的OOP语法和概念吧,单纯看这些概念总是越看催眠效果越好,现在带着实际问题去看,应该有所不同吧。不过我还是建议你在完成这个MVC的Hello World知道MVC是怎么回事之后下功夫打好OOP的基础,毕竟那是根本啊。

(5)怎么样,Controller真是个光说不练的家伙吧,看不到三行它就把你引向View了,那就看看View吧
View里有对应的子类,负责相应功能的显示。理解了Controller,View的代码就不难看了,难看的话也是因为混杂着HTML的原因,它所做的就是把Controller(Controller是个二道贩子,它的数据来自Model)给它的数据,然后塞到HTML中

View:

 <?php
//! View 类
/**
* 针对各个功能(list、post、delete)的各种View子类
* 被Controller调用,完成不同功能的网页显示
*/
class View { var $output; //用于保存输出HTML代码的字符串 function display() { //输出最终格式化的HTML数据
echo($this->output); }
}
class listView extends View //显示所有留言的子类
{
function __construct($notes)
{
foreach ($notes as $value)
{
$this->output.="<p><strong>访客姓名:</strong>".$value['name']."</p>".
"<p><strong>访客邮箱:</strong>".$value['email']."</p>".
"<p><strong>访客留言:</strong>".$value['content']."</p>".
"<p><strong>来访时间:</strong>".date("y-m-d H:i",$value['timedate'])."</p>".
"<p align=\"right\"><a href=\"index.php?action=delete&id=".$value['id']."\">删除留言</a>".
"<hr />";
} }
}
class postView extends View //发表留言的子类
{
function __construct($success)
{
if ($success)
$this->output="留言成功!<br><a href=\"".$_SERVER['PHP_SELF']."?action=list\">查看</a>";
else
$this->output="留言保存失败!";
}
}
class deleteView extends View //删除留言的子类
{
function __construct($success)
{
if ($success)
$this->output="留言删除成功!<br><a href=\"".$_SERVER['PHP_SELF']."?action=list\">查看</a>"; }
}
?>

之所以UI方面写得如此简陋,是因为这些工作可以交给Smarty这样的模板去做,而我们这里就像集中精力研究MVC,不想把Smarty扯进来,所以就这样凑合了,以后我们可以再把Smarty结合进来。

看了这个东西之后不知你是否对MVC的概念和实现更明白了一点。

PHP笔记09:PHP之 MVC理解的更多相关文章

  1. 机器学习实战(Machine Learning in Action)学习笔记————09.利用PCA简化数据

    机器学习实战(Machine Learning in Action)学习笔记————09.利用PCA简化数据 关键字:PCA.主成分分析.降维作者:米仓山下时间:2018-11-15机器学习实战(Ma ...

  2. 强化学习读书笔记 - 09 - on-policy预测的近似方法

    强化学习读书笔记 - 09 - on-policy预测的近似方法 参照 Reinforcement Learning: An Introduction, Richard S. Sutton and A ...

  3. ASP.NET MVC 学习笔记-7.自定义配置信息 ASP.NET MVC 学习笔记-6.异步控制器 ASP.NET MVC 学习笔记-5.Controller与View的数据传递 ASP.NET MVC 学习笔记-4.ASP.NET MVC中Ajax的应用 ASP.NET MVC 学习笔记-3.面向对象设计原则

    ASP.NET MVC 学习笔记-7.自定义配置信息   ASP.NET程序中的web.config文件中,在appSettings这个配置节中能够保存一些配置,比如, 1 <appSettin ...

  4. Java:并发笔记-09

    Java:并发笔记-09 说明:这是看了 bilibili 上 黑马程序员 的课程 java并发编程 后做的笔记 7. 共享模型之工具-2 原理:AQS 原理 对于 AQS 的原理这部分内容,没很好的 ...

  5. ASP.NET MVC 理解MVC模式

    ASP.NET MVC 理解MVC模式 PS:MVC出来很久了,工作上一直没机会用,所以我也没去学.出于兴趣,工作之余我将展开对MVC的深入学习,通过博文来记录所学所得,并希望能得到各位园友的斧正. ...

  6. Java框架-Spring MVC理解001

    Spring MVC理解 1.servlet--Spring MVC的本质 2.Spring MVC其实是一个工具,具体的理解可以分为两步:第一步,了解这个工具是怎么创建出来的:第二步,了解这个工具是 ...

  7. C++标准库第二版笔记 3 和异常的理解 1

    C++标准库第二版笔记 3 和异常的理解 1 差错和异常(error and exception)的处理 标准异常类(exception class) 定义于 分为: 1.语言本身支持的异常 2.标准 ...

  8. angular学习笔记(3)- MVC

    angular1学习笔记(3)- MVC --- MVC终极目标 - 模块化和复用 AngularJs的MVC是借助于$scope实现的!!! 神奇的$scope: 1.$scope是一个POJO(P ...

  9. JAVA自学笔记09

    JAVA自学笔记09 1.子类的方法会把父类的同名方法覆盖(重写) 2.final: 1)可修饰类.方法.变量 2)修饰类时:此时该类变为最终类,它将无法成为父类而被继承 3)修饰方法时:该方法将无法 ...

  10. .NET MVC 学习笔记(三)— MVC 数据显示

    . NET MVC 学习笔记(三)—— MVC 数据显示 在目前做的项目中,用的最多的数据展示控件就是table展示(说不是的请走开,不是一路人),以下详细阐述下table的使用方法. 先看效果: 上 ...

随机推荐

  1. vue-pdf的3.3.1版本build后多生成168个js文件

    当同事使用vue-pdf来浏览pdf之后,就发现build之后一堆散乱的js文件,真可怕! 果然google之后是它的原因.参考:Vue-pdf create 168 excess bundles i ...

  2. jquery连续滚动

    本文非常详细的讲解在jquery里实现图片或文字的连续循环滚动的方法. 连续循环滚动是我们在网页开发中经常要用到的特效,在jquery里,我们要实现文字或图片的连续循环滚动是非常简单的.出处:http ...

  3. easyui多选与接收不一致解决方案

    附代码: function batchRefund(){ if(editIndex != undefined) { $('#refundList').datagrid('endEdit', editI ...

  4. MFC—— AfxMessageBox

    AfxMessageBox 错误C2665:   “AfxMessageBox”:   2   个重载中没有一个可以转换所有参数类型 1,楼主发表于:2007-01-01 03:56:34同样的语句, ...

  5. 微信授权错误:"errcode":40163,"errmsg":"codebeenused

    微信网页授权获取code值回调两次的问题 1.说是域名原因,目前未测试,没有正确的域名 问题描述:在调用微信网页授权获取openid值时,先获取的code值,但是code值的接口 会走两次回调.而co ...

  6. Hadoop源码学习笔记(1) ——第二季开始——找到Main函数及读一读Configure类

    Hadoop源码学习笔记(1) ——找到Main函数及读一读Configure类 前面在第一季中,我们简单地研究了下Hadoop是什么,怎么用.在这开源的大牛作品的诱惑下,接下来我们要研究一下它是如何 ...

  7. 一:SpringCloud

    一:前提知识+相关说明 前提知识:springmvc+spring/springboot+mybatis+maven+git...... cloud技术的五大神兽: 面试题: 什么是微服务? 微服务之 ...

  8. ecstore关于smarty语法调用

    以下是smarty语法 转自http://www.phpwindow.com/ecstore_smarty2.html assign 属性 类型 是否必须 描述 var string yes 被赋值的 ...

  9. csharp: Gets a files formatted size.

    /* ASP.NET 默认上传文件是4M ,可以修改服务配置.. <system.web> <!-- 指示 ASP.NET 支持的最大文件上载大小. 该限制可用于防止因用户将大量文件 ...

  10. git杂记-打标签

    列出标签 $ git tag v0. v1. 创建标签 --添加附注标签(推荐):加上-a选项(annotated) $ git tag -a v1. -m 'my version 1.4' --添加 ...