単純な php MVC の例
原文 http://jcodecraeer.com/a/phpjiaocheng/2012/0305/10.html
?
この小さなプログラムには合計 6 つのファイルが含まれています。そのうち、index.php はプログラム エントリ、post.htm はメッセージ フォーム、lib フォルダー内のモデルとビューです。 , コントローラー 3 つのファイルはそれぞれ MVC を実装しており、DataAccess は単純なデータベース アクセス クラスです。実はこのプログラムは海外の人が書いたものです。
PHP コード:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
|
<?php
/**
* 一个用来访问MySQL的类
* 仅仅实现演示所需的基本功能,没有容错等
* 代码未作修改,只是把注释翻译一下,加了点自己的体会
*/
class DataAccess {
var $db; //用于存储数据库连接
var $query; //用于存储查询源
//! 构造函数.
/**
* 创建一个新的DataAccess对象
* @param $host 数据库服务器名称
* @param $user 数据库服务器用户名
* @param $pass 密码
* @param $db 数据库名称
*/
function __construct($host,$user,$pass,$db) {
$ this ->db=mysql_pconnect($host,$user,$pass); //连接数据库服务器
mysql_select_db($db,$ this ->db); //选择所需数据库
//特别注意$db和$this->db的区别
//前者是构造函数参数
//后者是类的数据成员
}
//! 执行SQL语句
/**
* 执行SQL语句,获取一个查询源并存储在数据成员$query中
* @param $sql 被执行的SQL语句字符串
* @return void
*/
function fetch($sql) {
$ this ->query=mysql_unbuffered_query($sql,$ this ->db); // Perform query here
}
//! 获取一条记录
/**
* 以数组形式返回查询结果的一行记录,通过循环调用该函数可遍历全部记录
* @return mixed
*/
function getRow () {
if ( $row=mysql_fetch_array($ this ->query,MYSQL_ASSOC) )
//MYSQL_ASSOC参数决定了数组键名用字段名表示
return $row;
else
return false ;
}
}
?>
|
?
では、Model クラスを紹介しましょう。
このクラスも非常に単純で、内部の関数が DataAccess を通じてデータベースにアクセスするためのものであることが一目でわかります。
PHP コード:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
|
<?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() { //获取全部留言
$ this ->dao->fetch( "SELECT * FROM note" );
}
function postNote($name,$content) { //插入一条新留言
$sql = "INSERT INTO `test`.`note`
(`id`, `name`, `content`, `ndate`, `add`)
VALUES (NULL, '$name', '$content', NULL, NULL);" ;
//echo $sql; //对于较复杂的合成SQL语句,<br />
//调试时用echo输出一下看看是否正确是一种常用的调试技巧
$ this ->dao->fetch($sql);
}
function deleteNote($id) { //删除一条留言,$id是该条留言的id
$sql = "DELETE FROM `test`.`note` WHERE `id`=$id;" ;
//echo $sql;
$ this ->dao->fetch($sql);
}
function getNote() { //获取以数组形式存储的一条留言
//View利用此方法从查询结果中读出数据并显示
if ( $note=$ this ->dao->getRow() )
return $note;
else
return false ;
}
}
?>
|
?
これら 2 つのカテゴリを読んだ後、これが以前に作成したプログラムに似ていることがわかるかもしれません。実際、MVC を理解していない場合は、これらをベースにして始めることができます。前のプログラムを 2 つのカテゴリに書きます。たとえば、すべてのコメントを表示するには、次のコードを記述するだけです:
PHP コード:
1
2
3
4
5
6
7
8
9
10
11
12
|
<?php
require_once( 'lib/DataAccess.php' );
require_once( 'lib/Model.php' );
$dao=& new DataAccess ( 'localhost' , 'root' , '' , 'test' );
$model=& new Model($dao);
$model->listNote();
while ($note=$model->getNote())
{
$output.= "姓名:$note[name]<br> 留言:<br> $note[content] <br> <hr />" ;
}
echo $output;
?>
|
require_once(
'lib/DataAccess.php'
);
<🎜>
<div class="行番号3 インデックス2 alt2">
<code class="js plain">require_once(
'lib/Model.php'
);
<🎜>
$dao=&
新しい
DataAccess (
'localhost'
,
'root'
,
''
,
'test'
);
<🎜>
$model=&
新しい
モデル($dao);
<🎜>
<div class="linenumber6index5alt1"><code class="js plain">$model->listNote();
<🎜>
while
($note=$model->getNote())
<div class="linenumber8index7alt1">
<code class="js plain">{
$output.=
"名前: $note[name]<br> メッセージ:<br> $note[content] < ;br> <hr>"
;
}
echo $output;
?>
?
とても優しいですね(笑)。
この「感情基盤」があれば、MVC に怯えることはありません。 さて、今日のメインは「Controller」のデビューです。
主要な構造を概観してみましょう。これには、Controller クラスと 3 つの派生サブクラスが含まれています (listController はメッセージ表示機能に対応し、postController はメッセージ投稿機能に対応し、deleteController はメッセージ削除機能に対応します)。
PHP コード:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
|
<?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); //继承其父类的构造函数
//该行的含义可以简单理解为:
//将其父类的构造函数代码复制过来
$ this ->view=& new listView($ this ->model);
//创建相应的View子类的对象来完成显示
//把model对象传给View子类供其获取数据
}
}
//用于控制添加留言的子类
class postController extends Controller{
function __construct (& $dao, $post) {
parent::__construct($dao);
$ this ->view=& new postView($ this ->model, $post);
//$post的实参为$_POST数组
//表单中的留言项目存储在该系统数组中
}
}
//用于控制删除留言的子类
class deleteController extends Controller{
function __construct (& $dao, $id) {
parent::__construct($dao);
$ this ->view=& new deleteView($ this ->model, $id);
}
}
?>
|
?
全体を閲覧した後は、詳細な学習を開始する予定です。アイデアを得るために、まず全体像を見てみましょう。 まず、メインエントランスのindex.phpがどのようにControllerを呼び出すかを見てみましょう:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
|
<html>
<head>
<meta http-equiv= "Content-Type" content= "text/html; charset=gb2312" />
<title>PHP MVC留言板</title>
</head>
<body>
<a href= "post.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' , '' , 'test' );
//根据$_GET["action"]取值的不同调用不同的控制器子类
$action=$_GET[ "action" ];
switch (
$action)
{
case "post" :
$controller=& new postController($dao,$_POST); break ;
case "list" :
$controller=& new listController($dao); break ;
case "delete" :
$controller=& new deleteController($dao,$_GET[ "id" ]); break ;
default :
$controller=& new listController($dao); break ; //默认为显示留言
}
$view=$controller->getView(); //获取视图对象
$view->display(); //输出HTML
?>
</body>
</html>
|
?
index.php を読むと、関数が $_GET["action"] を通じて指定され、異なる関数に対応することがわかります。
同じコントローラーのサブクラス。ここで、上にスクロールして (汚い言葉ではなく、ページを上にスクロールするという略語です^_^)、このコントローラー コードを詳しく見てみましょう。コメントは非常に詳細に書かれているはずですよね?
もっと詳しく知りたい場合は、OOP 構文と PHP5 の概念を見てください。これらの概念を簡単に理解すれば、見れば見るほど催眠効果が高まります。実際的な問題を抱えているのであれば、違うはずです。ただし、これを完了することをお勧めします
MVC の Hello World は MVC が何であるかを理解しており、OOP の優れた基盤を築くために熱心に取り組んでいます。
どうですか、コントローラーは本当に軽い話し方です
練習しないと、三本線が見えないとビューにつながってしまいますので、ビューを見てください。
View には対応するサブクラスがあり、対応する関数を表示する役割を果たします。理解した
コントローラーとビューのコードが醜いわけではありません。それは、必要なデータをモデルから取得して HTML に埋め込んでいるからです。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
|
<?php
//! View 类
/**
* 针对各个功能(list、post、delete)的各种 View子类
* 被Controller调用,完成不同功能的网页显示
*/
class View {
var
$model; //Model对象
var $output; //用于保存输出HTML代码 的字符串
//! 构造函数
/**
* 将参数中的Model对象接收并存储在成员变量$this->model中
* 供子类通 过model对象获取数据
*/
function __construct (&$model) {
$ this ->model=$model;
}
function
display() { //输出最终格式化的HTML数据
echo($ this ->output);
}
}
class
listView extends View //显示所有留言 的子类
{
function __construct(&$model)
{
parent::__construct(&$model); //继承父类的构造函数(详见Controller)
$ this ->model->listNote();
while ($note=$ this ->model->getNote()) //逐行获取数据
{
$ this ->output.= "姓名:$note[name]<br> 留 言:<br> $note[content]
<a href="" .$_SERVER[ 'PHP_SELF' ]. "?action=delete& amp;id=$note[id]">删除</a><br> <hr />" ;
}
}
}
class
postView extends View //发表留言的子类
{
function __construct(&$model, $post)
{
parent::__construct(&$model);
$ this ->model->postNote($post[name],$post[content]);
$ this ->output= "Note Post OK! .$_SERVER[ 'PHP_SELF' ]. "?action=list">查看</a>" ;
}
}
class
deleteView extends View //删除留言的子类
{
function __construct(&$model, $id)
{
parent::__construct(&$model);
$ this ->model->deleteNote($id);
$ this ->output= "Note Delete OK! .$_SERVER[ 'PHP_SELF' ]. "?action=list">查看</a>" ;
}
}
?>
|
UI が非常に雑に書かれている理由は、これらのタスクは Smarty などのテンプレートに任せることができるためであり、ここでは MVC の学習にのみ集中し、Smarty には関与したくないからです。
これで、将来的には Smarty を組み込むことができます。
これを読んだ後、MVC の概念と実装についてよりよく理解できたでしょうか。
私も初心者です
読者の皆様、これは MVC を理解することが目的です。専門家であれば、この分割と構造は MVC の概念に準拠していますか? ご意見をいただきたいと思います。他に何を改善する必要がありますか?
どこ?
もちろん、MVC について多くの議論が行われていることは周知の事実ですが、開発言語に関する議論と同様、学術的な議論がイノベーションに貢献することはありません。私たちがテクノロジーを学び、テクノロジーを使用する限り、
しっかりと深く勉強して、基本的な使い方をマスターしてから議論する必要があります。それが理解できないところで議論するのは時間の無駄です。
次のようなことが言われています
私が経験した MVC の利点についてお話します。たとえば、この例では、ユーザー名に基づいてメッセージをクエリする機能を追加する必要があります。モデルに関数を追加します。
クエリ関数 (これらの関数の使用法はストアド プロシージャと非常に似ていることが突然わかりました) と、対応するサブクラスがコントローラーとビューに追加されます。この分離の利点は、プログラム関数モジュールがプラグ アンド プレイであることです。
さらに、プログラム全体のロジックは非常に明確です。この機能は、要件が頻繁に変更される Web アプリケーションにとって価値があると思います。