首頁 後端開發 php教程 PHP MVC模式在网站架构中的实现分析_PHP教程

PHP MVC模式在网站架构中的实现分析_PHP教程

Jul 21, 2016 pm 03:40 PM
mvc php view web 主要 分析 實現 我們 架構 模式 瀏覽器 網站 視圖

视图(View)

“视图”主要指我们送到Web浏览器的最终结果??比如我们的脚本生成的HTML。当说到视图时,很多人想到的是模版,但是把模板方案叫做视图的正确性是值得怀疑的。

对视图来说,最重要的事情可能是它应该是“自我意识(self aware)”的,视图被渲染(render)时,视图的元素能意识到自己在更大框架中的角色。

XML为例,可以说XML在被解析时,DOM API有着这样的认知??一个DOM树里的节点知道它在哪里和它包含了什么。 (当一个XML文档中的节点用SAX解析时只有当解析到该节点时它才有意义。)

绝大多数模板方案使用简单的过程语言和这样的模板标签:

<p>{some_text}</p> <br><p>{some_more_text}</p>
登入後複製

它们在文档中没有意义,它们代表的意义只是PHP将用其他的东西来替换它。

如果你同意这种对视图的松散描述,你也就会同意绝大多数模板方案并没有有效的分离视图和模型。模板标签将被替换成什么存放在模型中。

在你实现视图时问自己几个问题:“全体视图的替换容易吗?”“实现一个新视图要多久?” “能很容易的替换视图的描述语言吗?(比如在同一个视图中用SOAP文档替换HTML文档)”

模型(Model)

模型代表了程序逻辑。(在企业级程序中经常称为业务层(business layer))

总的来说,模型的任务是把原有数据转换成包含某些意义的数据,这些数据将被视图所显示。通常,模型将封装数据查询,可能通过一些抽象数据类(数据访问层)来实现查询。举例说,你希望计算英国年度降雨量(只是为了给你自己找个好点的度假地),模型将接收十年中每天的降雨量,计算出平均值,再传递给视图。

控制器(controller)

简单的说控制器是Web应用中进入的HTTP请求最先调用的一部分。它检查收到的请求,比如一些GET变量,做出合适的反馈。在写出你的第一个控制器之前,你很难开始编写其他的PHP代码。最常见的用法是index.php中像switch语句的结构:

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

这段代码混用了面向过程和对象的代码,但是对于小的站点来说,这通常是最好的选择。虽然上边的代码还可以优化。

控制器实际上是用来触发模型的数据和视图元素之间的绑定的控件。

例子

这里是一个使用MVC模式的简单例子。

首先我们需要一个数据库访问类,它是一个普通类。

<?php <br>/** <br>* A simple class for querying <u><strong><font color="#6466b3">MySQL</font></strong></u> <br>*/ <br>class DataAccess { <br> /** <br> * Private <br> * $db stores a database resource <br> */ <br> var $db; <br> /** <br> * Private <br> * $query stores a query resource <br> */ <br> var $query; // Query resource <br><br> //! A constructor. <br> /** <br> * Constucts a new DataAccess object <br> * @param $host string hostname for dbserver <br> * @param $user string dbserver user <br> * @param $pass string dbserver user password <br> * @param $db string database name <br> */ <br> function DataAccess ($host,$user,$pass,$db) { <br>  $this->db=mysql_pconnect($host,$user,$pass); <br>  mysql_select_db($db,$this->db); <br> } <br><br> //! An accessor <br> /** <br> * Fetches a query resources and stores it in a local member <br> * @param $sql string the database query to run <br> * @return void <br> */ <br> function fetch($sql) { <br> $this->query=mysql_unbuffered_query($sql,$this->db)
登入後複製
; // Perform query here <br> } <br><br> //! An accessor <br> /** <br> * Returns an associative array of a query row <br> * @return mixed <br> */ <br> function getRow () { <br>  if ( $row=mysql_fetch_array($this->query,MYSQL_ASSOC) ) <br>   return $row; <br>  else <br>   return false; <br> } <br>} <br>?>
登入後複製

在它上边放上模型。

<?php <br>/** <br>* Fetches "products" from the database <br>*/ <br>class ProductModel { <br> /** <br> * Private <br> * $dao an instance of the DataAccess class <br> */ <br> var $dao; <br><br> //! A constructor. <br> /** <br> * Constucts a new ProductModel object <br> * @param $dbobject an instance of the DataAccess class <br> */ <br> function ProductModel (&$dao) { <br>  $this->dao=& $dao; <br> } <br><br> //! A manipulator <br> /** <br> * Tells the $dboject to store this query as a resource <br> * @param $start the row to start from <br> * @param $rows the number of rows to fetch <br> * @return void <br> */ <br> function listProducts($start=1,$rows=50) { <br> $this->dao->fetch("SELECT * FROM products LIMIT ".$start.", ".$rows); <br> } <br><br> //! A manipulator <br> /** <br> * Tells the $dboject to store this query as a resource <br> * @param $id a primary key for a row <br> * @return void <br> */ <br> function listProduct($id) { <br> $this->dao->fetch("SELECT * FROM products WHERE PRODUCTID='".$id."'"); <br> } <br><br> //! A manipulator <br> /** <br> * Fetches a product as an associative array from the $dbobject <br> * @return mixed <br> */ <br> function getProduct() { <br>  if ( $product=$this->dao->getRow() ) <br>   return $product; <br>  else <br>   return false; <br> } <br>} <br>?>
登入後複製

有一点要注意的是,在模型和数据访问类之间,它们的交互从不会多于一行??没有多行被传送,那样会很快使程式慢下来。同样的程式对于使用模式的类,它只需要在内存中保留一行(Row)??其他的交给已保存的查询资源(query resource)??换句话说,我们让MYSQL替我们保持结果。

接下来是视图??我去掉了HTML以节省空间,你可以查看这篇文章的完整代码。

<?php <br>/** <br>* Binds product data to HTML rendering <br>*/ <br>class ProductView { <br> /** <br> * Private <br> * $model an instance of the ProductModel class <br> */ <br> var $model; <br><br> /** <br> * Private <br> * $output rendered HTML is stored here for display <br> */ <br> var $output; <br><br> //! A constructor. <br> /** <br> * Constucts a new ProductView object <br> * @param $model an instance of the ProductModel class <br> */ <br> function ProductView (&$model) { <br>  $this->model=& $model; <br> } <br><br> //! A manipulator <br> /** <br> * Builds the top of an HTML page <br> * @return void <br> */ <br> function header () { <br><br> } <br><br> //! A manipulator <br> /** <br> * Builds the bottom of an HTML page <br> * @return void <br> */ <br> function footer () { <br><br> } <br><br> //! A manipulator <br> /** <br> * Displays a single product <br> * @return void <br> */ <br> function productItem($id=1) { <br>  $this->model->listProduct($id); <br>  while ( $product=$this->model->getProduct() ) { <br>    // Bind data to HTML <br>  } <br> } <br><br> //! A manipulator <br> /** <br> * Builds a product table <br> * @return void <br> */ <br> function productTable($rownum=1) { <br>  $rowsperpage='20'; <br>  $this->model->listProducts($rownum,$rowsperpage); <br>  while ( $product=$this->model->getProduct() ) { <br>    // Bind data to HTML <br>  } <br> } <br><br> //! An accessor <br> /** <br> * Returns the rendered HTML <br> * @return string <br> */ <br> function display () { <br>  return $this->output; <br> } <br>} <br>?>
登入後複製

最后是控制器,我们将把视图实现为一个子类。

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

 

注意这不是实现MVC的唯一方式??比如你可以用控制器实现模型同时整合视图。这只是演示模式的一种方法

我们的index.php 文件看起来像这样:

<?php <br>require_once('lib/DataAccess.php'); <br>require_once('lib/ProductModel.php'); <br>require_once('lib/ProductView.php'); <br>require_once('lib/ProductController.php'); <br><br>$dao=& new DataAccess ('localhost','user','pass','dbname'); <br>$productModel=& new ProductModel($dao); <br>$productController=& new ProductController($productModel,$_GET); <br>echo $productController->display(); <br>?>
登入後複製

漂亮而简单。

我们有一些使用控制器的技巧,在PHP中你可以这样做:

$this->{$_GET['method']}($_GET['param']);
登入後複製

一个建议是你最好定义程序URL的名字空间形式(namespace),那样它会比较规范比如:

"index.php?class=ProductView&method=productItem&id=4"
登入後複製

通过它我们可以这样处理我们的控制器:

$view=new $_GET['class']; <br>$view->{$_GET['method']($_GET['id']);
登入後複製

有时候,建立控制器是件很困难的事情,比如当你在开发速度和适应性之间权衡时。一个获得灵感的好去处是Apache group 的Java Struts,它的控制器完全是由XML文档定义的。

www.bkjia.comtruehttp://www.bkjia.com/PHPjc/321386.htmlTechArticle视图(View) “视图”主要指我们送到Web浏览器的最终结果??比如我们的脚本生成的 HTML 。当说到视图时,很多人想到的是模版,但是把 模...
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

IIS和PHP的兼容性:深度潛水 IIS和PHP的兼容性:深度潛水 Apr 22, 2025 am 12:01 AM

IIS和PHP可以兼容,通過FastCGI實現。 1.IIS通過配置文件將.php文件請求轉發給FastCGI模塊。 2.FastCGI模塊啟動PHP進程處理請求,提高性能和穩定性。 3.實際應用中需注意配置細節、錯誤調試和性能優化。

USDT轉賬地址錯誤怎麼辦 新手小白指南 USDT轉賬地址錯誤怎麼辦 新手小白指南 Apr 21, 2025 pm 12:12 PM

USDT轉賬地址錯誤後,首先確認轉賬已發生,然後根據錯誤類型採取措施。 1.確認轉賬:查看交易記錄,獲取並在區塊鏈瀏覽器上查詢交易哈希值。 2.採取措施:若地址不存在,等待資金退回或聯繫客服;若為無效地址,聯繫客服並尋求專業幫助;若轉給了他人,嘗試聯繫收款方或尋求法律幫助。

web3交易平台排行榜_web3全球交易所前十名匯總 web3交易平台排行榜_web3全球交易所前十名匯總 Apr 21, 2025 am 10:45 AM

幣安是全球數字資產交易生態的霸主,其特點包括:1. 日均交易量突破$1500億,支持500 交易對,覆蓋98%主流幣種;2. 創新矩陣涵蓋衍生品市場、Web3佈局和教育體系;3. 技術優勢為毫秒級撮合引擎,峰值處理量達140萬筆/秒;4. 合規進展持有15國牌照,並在歐美設立合規實體。

兩個交易所之間可以互相轉幣嗎 交易所之間可以轉幣嗎 兩個交易所之間可以互相轉幣嗎 交易所之間可以轉幣嗎 Apr 22, 2025 am 08:57 AM

可以。兩個交易所之間可以互相轉幣,只要支持相同的幣種和網絡。步驟包括:1. 獲取收款地址,2. 發起提幣請求,3. 等待確認。注意事項:1. 選擇正確的轉賬網絡,2. 仔細核對地址,3. 了解手續費,4. 注意到賬時間,5. 確認交易所支持該幣種,6. 注意最小提幣數量。

什麼是鏈上交易?全球鏈上交易所有哪些? 什麼是鏈上交易?全球鏈上交易所有哪些? Apr 22, 2025 am 10:06 AM

歐盟MiCA合規認證,覆蓋50 法幣通道,冷存儲比例95%,零安全事件記錄。美國SEC持牌平台,法幣直購便捷,冷存儲比例98%,機構級流動性,支持大額OTC和自定義訂單,多級清算保護。

歐易交易所如何註冊賬戶 歐易交易所註冊教程 歐易交易所如何註冊賬戶 歐易交易所註冊教程 Apr 24, 2025 pm 02:06 PM

註冊歐易賬戶的步驟如下:1.準備有效郵箱或手機號和穩定網絡。 2.訪問歐易官網。 3.進入註冊頁面。 4.選擇郵箱或手機號註冊,填寫信息。 5.獲取並填寫驗證碼。 6.同意用戶協議。 7.完成註冊並登錄,進行KYC和設置安全措施。

幣圈十大行情網站的使用技巧與推薦2025 幣圈十大行情網站的使用技巧與推薦2025 Apr 22, 2025 am 08:03 AM

國內用戶適配方案包括合規渠道和本地化工具。 1. 合規渠道:通過OTC平台如Circle Trade進行法幣兌換,境內需通過香港或海外平台。 2. 本地化工具:使用幣圈網獲取中文資訊,火幣全球站提供元宇宙交易終端。

幣安下載鏈接 幣安下載路徑 幣安下載鏈接 幣安下載路徑 Apr 24, 2025 pm 02:12 PM

安全下載幣安APP需通過官方渠道:1. 訪問幣安官網,2. 找到並點擊APP下載入口,3. 選擇掃描二維碼、應用商店或直接下載APK文件的方式下載,確保鏈接和開發者信息真實,開啟雙重驗證保護賬戶安全。

See all articles