天天躁日日躁狠狠躁AV麻豆-天天躁人人躁人人躁狂躁-天天澡夜夜澡人人澡-天天影视香色欲综合网-国产成人女人在线视频观看-国产成人女人视频在线观看

MVC模式的PHP實(shí)現(xiàn)

作者:Harry Fuecks 翻譯:Easy Chen 
MVC模式在網(wǎng)站架構(gòu)中十分常見。它允許我們建立一個(gè)三層結(jié)構(gòu)的應(yīng)用程式,從代碼中分離出有用的層,幫助設(shè)計(jì)師和開發(fā)者協(xié)同工作以及提高我們維護(hù)和擴(kuò)展既有程式的能力。

視圖(View)

“視圖”主要指我們送到Web瀏覽器的最終結(jié)果――比如我們的腳本生成的HTML。當(dāng)說到視圖時(shí),很多人想到的是模版,但是把模板方案叫做視圖的正確性是值得懷疑的。

對(duì)視圖來說,最重要的事情可能是它應(yīng)該是“自我意識(shí)(self aware)”的,視圖被渲染(render)時(shí),視圖的元素能意識(shí)到自己在更大框架中的角色。

以XML為例,可以說XML在被解析時(shí),DOM API有著這樣的認(rèn)知――一個(gè)DOM樹里的節(jié)點(diǎn)知道它在哪里和它包含了什么。 (當(dāng)一個(gè)XML文檔中的節(jié)點(diǎn)用SAX解析時(shí)只有當(dāng)解析到該節(jié)點(diǎn)時(shí)它才有意義。)

絕大多數(shù)模板方案使用簡單的過程語言和這樣的模板標(biāo)簽:

<p>{some_text}</p>
<p>{some_more_text}</p>


它們?cè)谖臋n中沒有意義,它們代表的意義只是php將用其他的東西來替換它。

如果你同意這種對(duì)視圖的松散描述,你也就會(huì)同意絕大多數(shù)模板方案并沒有有效的分離視圖和模型。模板標(biāo)簽將被替換成什么存放在模型中。

在你實(shí)現(xiàn)視圖時(shí)問自己幾個(gè)問題:“全體視圖的替換容易嗎?”“實(shí)現(xiàn)一個(gè)新視圖要多久?” “能很容易的替換視圖的描述語言嗎?(比如在同一個(gè)視圖中用SOAP文檔替換HTML文檔)”


模型(Model)

模型代表了程序邏輯。(在企業(yè)級(jí)程序中經(jīng)常稱為業(yè)務(wù)層(business layer))

總的來說,模型的任務(wù)是把原有數(shù)據(jù)轉(zhuǎn)換成包含某些意義的數(shù)據(jù),這些數(shù)據(jù)將被視圖所顯示。通常,模型將封裝數(shù)據(jù)查詢,可能通過一些抽象數(shù)據(jù)類(數(shù)據(jù)訪問層)來實(shí)現(xiàn)查詢。舉例說,你希望計(jì)算英國年度降雨量(只是為了給你自己找個(gè)好點(diǎn)的度假地),模型將接收十年中每天的降雨量,計(jì)算出平均值,再傳遞給視圖。


控制器(controller)

簡單的說控制器是Web應(yīng)用中進(jìn)入的HTTP請(qǐng)求最先調(diào)用的一部分。它檢查收到的請(qǐng)求,比如一些GET變量,做出合適的反饋。在寫出你的第一個(gè)控制器之前,你很難開始編寫其他的php代碼。最常見的用法是index.php中像switch語句的結(jié)構(gòu):

<?php
switch ($_GET['viewpage']) {
case "news":
$page=new NewsRenderer;
break;
case "links":
$page=new LinksRenderer;
break;
default:
$page=new HomePageRenderer;
break;
}
$page->display();
?>


這段代碼混用了面向過程和對(duì)象的代碼,但是對(duì)于小的站點(diǎn)來說,這通常是最好的選擇。雖然上邊的代碼還可以優(yōu)化。

控制器實(shí)際上是用來觸發(fā)模型的數(shù)據(jù)和視圖元素之間的綁定的控件。


例子

這里是一個(gè)使用MVC模式的簡單例子。
首先我們需要一個(gè)數(shù)據(jù)庫訪問類,它是一個(gè)普通類。

<?php
/**
* A simple class for querying MySQL
*/
class DataAccess {
/**
* Private
* $db stores a database resource
*/
var $db;
/**
* Private
* $query stores a query resource
*/
var $query; // Query resource

//! A constructor.
/**
* Constucts a new DataAccess object
* @param $host string hostname for dbserver
* @param $user string dbserver user
* @param $pass string dbserver user password
* @param $db string database name
*/
function DataAccess ($host,$user,$pass,$db) {
$this->db=mysql_pconnect($host,$user,$pass);
mysql_select_db($db,$this->db);
}

//! An accessor
/**
* Fetches a query resources and stores it in a local member
* @param $sql string the database query to run
* @return void
*/
function fetch($sql) {
$this->query=mysql_unbuffered_query($sql,$this->db); // Perform query here
}

//! An accessor
/**
* Returns an associative array of a query row
* @return mixed
*/
function getRow () {
if ( $row=mysql_fetch_array($this->query,MYSQL_ASSOC) )
return $row;
else
return false;
}
}
?>


在它上邊放上模型。

<?php
/**
* Fetches "products" from the database
*/
class ProductModel {
/**
* Private
* $dao an instance of the DataAccess class
*/
var $dao;

//! A constructor.
/**
* Constucts a new ProductModel object
* @param $dbobject an instance of the DataAccess class
*/
function ProductModel (&$dao) {
$this->dao=& $dao;
}

//! A manipulator
/**
* Tells the $dboject to store this query as a resource
* @param $start the row to start from
* @param $rows the number of rows to fetch
* @return void
*/
function listProducts($start=1,$rows=50) {
$this->dao->fetch("SELECT * FROM products LIMIT ".$start.", ".$rows);
}

//! A manipulator
/**
* Tells the $dboject to store this query as a resource
* @param $id a primary key for a row
* @return void
*/
function listProduct($id) {
$this->dao->fetch("SELECT * FROM products WHERE PRODUCTID='".$id."'");
}

//! A manipulator
/**
* Fetches a product as an associative array from the $dbobject
* @return mixed
*/
function getProduct() {
if ( $product=$this->dao->getRow() )
return $product;
else
return false;
}
}
?>


有一點(diǎn)要注意的是,在模型和數(shù)據(jù)訪問類之間,它們的交互從不會(huì)多于一行――沒有多行被傳送,那樣會(huì)很快使程式慢下來。同樣的程式對(duì)于使用模式的類,它只需要在內(nèi)存中保留一行(Row)――其他的交給已保存的查詢資源(query resource)――換句話說,我們讓MYSQL替我們保持結(jié)果。

接下來是視圖――我去掉了HTML以節(jié)省空間,你可以查看這篇文章的完整代碼。

<?php
/**
* Binds product data to HTML rendering
*/
class ProductView {
/**
* Private
* $model an instance of the ProductModel class
*/
var $model;

/**
* Private
* $output rendered HTML is stored here for display
*/
var $output;

//! A constructor.
/**
* Constucts a new ProductView object
* @param $model an instance of the ProductModel class
*/
function ProductView (&$model) {
$this->model=& $model;
}

//! A manipulator
/**
* Builds the top of an HTML page
* @return void
*/
function header () {

}

//! A manipulator
/**
* Builds the bottom of an HTML page
* @return void
*/
function footer () {

}

//! A manipulator
/**
* Displays a single product
* @return void
*/
function productItem($id=1) {
$this->model->listProduct($id);
while ( $product=$this->model->getProduct() ) {
// Bind data to HTML
}
}

//! A manipulator
/**
* Builds a product table
* @return void
*/
function productTable($rownum=1) {
$rowsperpage='20';
$this->model->listProducts($rownum,$rowsperpage);
while ( $product=$this->model->getProduct() ) {
// Bind data to HTML
}
}

//! An accessor
/**
* Returns the rendered HTML
* @return string
*/
function display () {
return $this->output;
}
}
?>


最后是控制器,我們將把視圖實(shí)現(xiàn)為一個(gè)子類。

<?php
/**
* Controls the application
*/
class ProductController extends ProductView {

//! A constructor.
/**
* Constucts a new ProductController object
* @param $model an instance of the ProductModel class
* @param $getvars the incoming HTTP GET method variables
*/
function ProductController (&$model,$getvars=null) {
ProductView::ProductView($model);
$this->header();
switch ( $getvars['view'] ) {
case "product":
$this->productItem($getvars['id']);
break;
default:
if ( empty ($getvars['rownum']) ) {
$this->productTable();
} else {
$this->productTable($getvars['rownum']);
}
break;
}
$this->footer();
}
}
?>


注意這不是實(shí)現(xiàn)MVC的唯一方式――比如你可以用控制器實(shí)現(xiàn)模型同時(shí)整合視圖。這只是演示模式的一種方法。

我們的index.php 文件看起來像這樣:

<?php
require_once('lib/DataAccess.php');
require_once('lib/ProductModel.php');
require_once('lib/ProductView.php');
require_once('lib/ProductController.php');

$dao=& new DataAccess ('localhost','user','pass','dbname');
$productModel=& new ProductModel($dao);
$productController=& new ProductController($productModel,$_GET);
echo $productController->display();
?>


漂亮而簡單。

我們有一些使用控制器的技巧,在php中你可以這樣做:

$this->{$_GET['method']}($_GET['param']);


一個(gè)建議是你最好定義程序URL的名字空間形式(namespace),那樣它會(huì)比較規(guī)范比如:

"index.php?class=ProductView&method=productItem&id=4"


通過它我們可以這樣處理我們的控制器:

$view=new $_GET['class'];
$view->{$_GET['method']($_GET['id']);


有時(shí)候,建立控制器是件很困難的事情,比如當(dāng)你在開發(fā)速度和適應(yīng)性之間權(quán)衡時(shí)。一個(gè)獲得靈感的好去處是Apache group 的Java Struts,它的控制器完全是由XML文檔定義的。 

php技術(shù)MVC模式的PHP實(shí)現(xiàn),轉(zhuǎn)載需保留來源!

鄭重聲明:本文版權(quán)歸原作者所有,轉(zhuǎn)載文章僅為傳播更多信息之目的,如作者信息標(biāo)記有誤,請(qǐng)第一時(shí)間聯(lián)系我們修改或刪除,多謝。

主站蜘蛛池模板: 一本久道久久综合狠狠躁AV | 国产探花在线精品一区二区 | 国产欧美精品国产国产专区 | ppypp日本欧美一区二区 | www.av在线| 国精品产露脸偷拍视频 | 亚洲中文字幕欧美自拍一区 | 免费精品在线视频 | 渔夫床满艳史bd高清在线直播 | 2012中文字幕手机在线 | 女同给老师下媚药 | 美女爽到嗷嗷嗷叫 | 免费a毛片 | 99热久久视频只有精品6 | 我的好妈妈8高清在线观看WWW | a国产成人免费视频 | 久久精品视频在线直播6 | 免费一区二区三区久久 | 久久无码AV亚洲精品色午夜 | 久久vs国产综合色 | 久久青草免费91线频观看站街 | 伊人久久大香线蕉综合色啪 | 打卡中国各地奋斗第一线 | 快穿之H啪肉| 久草在线新是免费视频 | 91免费网站在线看入口黄 | 97色伦图区97色伦综合图区 | 羞羞答答影院在线 | 午夜日本大胆裸艺术 | 伊人久久综合 | 超碰在线观看 | 999视频精品全部免费观看 | 男男高H啪肉Np文多攻多一受 | 天天躁日日躁狠狠躁AV麻豆 | 丝袜美腿美女被狂躁在线观看 | 国产日韩精品一区二区三区在线 | 三级黃60分钟 | 空姐内射出白浆10p 空姐厕所啪啪啪 | 亚洲福利网站 | 女人 我狠狠疼你 | 国产精品福利电影 |