中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

PHP框架的三層架構設計真的合適么?

發布時間:2020-08-06 23:13:22 來源:網絡 閱讀:8244 作者:wangweiak47 欄目:web開發

    對于基本的Web開發,我們已經習慣了MVC架構。模型層(M)提供持久化數據對象與數據訪問,控制層(C)完成業務邏輯處理,視圖層(V)提供模板表現。其中控制層與模型層和視圖層交互形成整個系統。

    這種分層方式在邏輯上實現了解耦與分離,很多語言如Java和Python的框架都有各自的實現方式,如Struts采用Bean+JSP+Hibernate的方式實現。Django采用中間件的方式實現。無論是JAVA框架的實現方式還是Python框架的實現方式,都比較好的解決了MVC之間的交互問題,使得每個層次成為單獨的構件,每一層的構件可復用在其它地方。如Java Bean除了可供JSP使用,還可包裝成Soap服務。這樣既保證了層之間的邏輯分離,也保證了層之間的物理分離。如Java Bean可以單獨被部署到分布式應用服務器上。EJB就是一個很好的例子。而對于目前廣泛應用的一些PHP框架,在實現上感覺缺少對物理獨立性的考慮。

    以Yii框架為例子來說,Yii框架的組織結構大致如下所示:

           Site

                |____resources

                |____protected

                        |____config

                        |____controllers

                        |____models

                        |____views

                        |____components

                |____framework

                |____index.php

        

    resources代表站點的一些資源性資料,如圖片、樣式表等。freamework為框架核心檔。index.php為入口文件,所有訪問路徑均以index.php后跟參數為標準。而protected內就是業務邏輯需要的MVC三層及系統需要的一些配置信息了。protected內的componets下是系統的組件類,如果有與系統業務流程無關,但是在業務邏輯中需要的函數庫,可以將它們作為組件放到這個目錄下,如果配置文件內注冊了該組件,在系統運行時會產生它們的實例以供調用。執行的流程大致如下圖所示:


PHP框架的三層架構設計真的合適么?

PHP框架的三層架構設計真的合適么?

    根據上圖可以看出,Action需要同時與Model層與View層進行交互,在Action內,不僅有業務邏輯,還需調用Model層的方法和View層的方法。這樣,業務邏輯與Model層、View層就存在了緊耦合的關系。這種層次結構應用在基本的網站上還是可以滿足要求,但是不具備擴展性和可修改性。如果現在想把業務邏輯包裝稱REST風格或SOAP服務,那么只能重新寫一次包含業務邏輯的Action,因為現在的Action里已經包含了頁面的輸出方法,而不是單純的數據結果。對于需要使用同一動態數據展示不同表現形式的需求,也只能通過判斷(修改)的方式而不能通過增加類或簡單Action(擴展)的方式實現。這違反了面向對象的開放封閉原則。由于系統需求往往是頻繁的變更的,如果我們常常的修改現有的代碼,不僅會造成現有系統代碼結構的混亂,而且極易造成隱藏的,難以發現的錯誤。所以,只有通過擴展來實現需求的變更,對系統來說才是最安全的。我們的工作才會更加的輕松和高效。

    既然Yii提供的源碼不能完美的解決擴展性和可修改性的問題,那么我們何不對它進行一次小小的改造,使它能勝任更加高的要求呢。俗話說的好,在軟件的世界里,加一層能解決所有的問題。所以,我們也決定使用“加一層”的辦法,以提高我們系統的可擴展性與可修改性。由于Yii是通過URI路由來查找Action并進行相應操作,最后也是通過Action方法產生響應結果的。所以,為了不破壞Yii的框架結構,我們只能在Action的下方增加一層,作為專門的業務邏輯層。為了偷懶,我們借鑒Java的叫法,稱它為bean層。此時,Action就最為一個專門的包裝層,包裝bean的邏輯,然后與View層交互產生頁面,或直接輸出數據。這樣如果我想把業務流程包裝成SOAP服務,只需增加一個Action即可,無需重寫業務邏輯。如果有多種視圖顯示要求,也無須重寫業務邏輯,只需擴展Action即可。下面用代碼來說明“這一層”是如何加上去的。

    首先我們在protected目錄下新建一個beans目錄,然后在components內新建LoadBean.php文件,用于實例化bean類及獲取bean對象。beans下的文件以XXXBean.php命名,如SiteBean.php。在beans下新建一個configure.php文件。此文件是bean加載的配置文件,以實現IOC之用。新結構如下所示:

           Site

                |____resources

                |____protected

                        |____config

                        |____controllers

                        |____models

                        |____views

                        |____beans

                                |____configure.php

                                |____SiteBean.php

                        |____components

                                |____LoadBean.php

                |____framework

                |____index.php

        

    beans下是專門負責業務邏輯的地方,Action內只需調用beans下的業務邏輯并提供輸出即可,無需再寫業務邏輯代碼。為了達到以上要求,我們需要對Yii的代碼做少許修改。首先找到框架核心內的CWebApplication.php文件,它的位置是framework/web/CWebApplication.php。 在該文件內添加一個getBeanPath與一個reloadBeans方法。代碼如下:

 public function getBeanPath(){
  return $this->_controllerPath=$this->getBasePath().DIRECTORY_SEPARATOR.'beans';
 }
 public function reloadBeans(){
  $beanPath = $this->getBeanPath();
  if(is_dir($beanPath)){
   $current_dir =opendir($beanPath);
   while(($file = readdir($current_dir))!==false){
    if($file=='.' OR $file=='..')
     continue;
    require($beanPath.DIRECTORY_SEPARATOR.$file);
   }
  }
 }


    然后找到該文件內的runController方法,在runController方法的開頭處調用reloadBeans方法:

        

 public function runController($route)
 {
  $this->reloadBeans();
  if(($ca=$this->createController($route))!==null)
  {
   list($controller,$actionID)=$ca;
   $oldController=$this->_controller;
   $this->_controller=$controller;
   $controller->init();
   $controller->run($actionID);
   $this->_controller=$oldController;
  }
  else
   throw new CHttpException(404,Yii::t('yii','Unable to resolve the request "{route}".',
    array('{route}'=>$route===''?$this->defaultController:$route)));
 }


    第三步,打開剛才新建的LoadBean.php文件,添加以下代碼:

class LoadBean {
 private $objs;
 public function init(){
  $beanconfig = Yii::app()->basePath.'\beans\configure.php';
  $beans = require $beanconfig;
  foreach($beans as $bean){
   if (!$this->objs[$bean] instanceof $bean.'Bean'){
    $class = $bean.'Bean';
    if(class_exists($class)){
     $this->objs[$bean] = new $class($bean);
    }
   }
  }
 }
 public function obj($name){
  try{
   if (array_key_exists($name,$this->objs)){
    return $this->objs[$name];
   }else{
    throw new Exception('bean name error');
   }
  }catch(Exception $e){
   echo $e->getMessage();
  }
 }
}


    第四步,找到protected/config/main.php文件,添加以下代碼:

  'beans'=>array(
   'class'=>'LoadBean',
  ),

讓系統在初始化時加載第三步添加的LoadBean類。

    

    第五步,找到protected/beans/SiteBean.php,添加以下代碼:

class SiteBean extends Controller{
 public function abc(){
      return123;
 }
}

此abc方法即是我們的業務邏輯代碼。

        

    第六步,找到protected/beans/configure.php,添加以下代碼:

 return array(
  'Site',
  );

此'Site'即為SiteBean類的'Site'名。

    

    第七步,實現Action方法,找到protected/controllers/SiteController.php文件(如沒有,可直接創建),代碼如下:

class SiteController extends Controller{
     public function actionIndex(){
          print_r(Yii::app()->beans->obj('Site')->abc());
     }
}

Action類不直接與Bean類交互,而是通過組件類做代理進行通訊,使Action與Bean也實現了分離。


    此時,利用瀏覽器訪問http://yourdomain/index.php?r=Site/index,即可顯示123。在此,我們實現了業務邏輯與Action的分離,增加了系統的擴展性與可修改性,bean實現了物理部署獨立。形成了我們的四層架構。

        

PHP框架的三層架構設計真的合適么?

PHP框架的三層架構設計真的合適么?


向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

鸡西市| 象州县| 耿马| 安顺市| 龙南县| 板桥市| 会理县| 江山市| 布拖县| 忻州市| 金华市| 涟源市| 青海省| 石林| 太和县| 邵东县| 剑川县| 资讯| 北宁市| 蛟河市| 将乐县| 同德县| 陵水| 富平县| 米易县| 中方县| 台南市| 资溪县| 兖州市| 万州区| 多伦县| 南涧| 玛多县| 舟山市| 甘孜县| 克东县| 翼城县| 南和县| 丹寨县| 嵩明县| 呼玛县|