當前位置:
首頁 > 知識 > PHP後端該如何組織項目結構

PHP後端該如何組織項目結構

全棧系列後端項目結構的思考,不夸夸其談,只想寫好代碼。

這是後端開發者從零做一個移動應用的後端部分第二篇。介紹下一個新項目,後端該如何從零去搭建。我們先假設這個項目由兩部組成

提供給wap站點、app使用的api;

提供給運營人員使用的管理後台。

整個項目採用 Phalcon,項目的demo可以 點這裡 參閱

備註:跟隨文章進度,項目持續更新,最後會與配套的wap app形成一個整體

項目最終至少會包含以下內容:

項目結構回顧

後端系統一般都是採用 MVC 結構(這裡均以PHP為例),M 代表模型,V 代表視圖,C 代表控制器。我在啰嗦幾句

Model指的是數據模型,這個數據模型包括你的Mysql中的表結構,或者redis的緩存對象結構都可以。它代表一個數據操作單元。

View指的展示給用戶瀏覽、直接操作的界面,這個大家都懂,不多說

Controller 控制器,主要是為了隔離 View 與 Model 直接打交道,他做為一個中間人,兩頭傳遞小紙條。

在我過往的項目中,我主要的困惑在於,業務邏輯是放在 C 還是放在 M。

從對象角度出發,業務邏輯無非就是操作數據,要麼讀取,要麼修改,那麼應該放在M層,因為一個對象應該有自己的屬性與方法。

業務放在M中

實際工作中我們常常有這樣的場景,比如:讀取一個遊戲列表數據,數據包括遊戲的詳情以及遊戲的版本信息以及下載信息。因為遊戲app會存在升級,因此一個遊戲會對應多個包。那麼這裡至少存在兩個model

遊戲詳情model,包括遊戲的名稱,logo等基本信息

遊戲的包信息model,包括包所屬平台,大小,下載地址,版本信息等

那麼這個動作的方法應該封裝在哪裡呢?以前的做法是,分別封裝對應的操作到對應的model,然後在控制器中分別調用。說回到這裡,遊戲model封裝了查詢遊戲列表的method,然後包model封裝了根據遊戲id查詢包信息的method。

然後我們在控制器中分別調用這個兩個方法,然後再進行組裝,把遊戲對應的包設置到對應的遊戲中。

那麼有一個問題,假設我們在遊戲詳情這個控制器方法中,需要返回一個相關遊戲的集合,難道又重複一次上面的操作?

有人會說把處理遊戲部分抽離成一個公共方法,那麼假設是要在新聞詳情裡邊調用呢?這根本不該在同一個控制器裡邊啊!

業務放在C中

上面我們把方法放在model中遇到了復用的小麻煩,那麼繼續看看放到controller中會怎樣?

這個時候的一個好處是:我們可以使用連接查詢,將剛剛的2次查詢,通過連接查詢1次完成,對於mysql的時間減少了,程序性能提升,然後對查詢結果啪啪啪處理完成。

好吧,不往後面說了,相信大家已經發現了,這個查詢過程還是不可復用。自然而然的,我們這裡應該想到,將它提煉成一個方法,無法滿足其他控制器使用(一個控制器調用另外一個控制器的想法想都別想啊)。那麼只能提煉成一個類了,這個類來封裝所有的業務。

這樣之後,任何需要遊戲列表數據的地方,直接調用這個GameServer(假設封裝的業務邏輯都放在xxxServer中)就可以獲得相同的數據,然後如果業務變動,我們也只需要改動這一處,所有地方得到的數據也將會是一致的。

因此通過回顧,我們得出我們的後端項目需要一個server的層次,來存放業務邏輯。

Server層存在的意義

分離出來的這一層,集中涵蓋了所有的業務功能,極大的提高了代碼的復用性,除了不同控制器不同方法的直接使用,還包括了不同模塊之間的復用。

但是在不同模塊之前服用,server層也需要考慮一些額外的東西,比如我們有一個app api模塊,有一個後台管理模塊。那麼都是獲取列表數據,可能給app api模塊可能不需要某些欄位,但是後台管理需要知悉全部內容,以及後台用戶許可權上的一些問題。這些部分可以繼續進行拆分,與server組合。需要結合自己的業務來進行管理。

我個人實踐過程中代碼的另外一個好處是,server層從某種層度上讓C層變得簡單,這讓團隊中的新人能夠快速上手接觸代碼。比如小明是團隊新人,那麼在他熟悉所使用框架的前提下,他可以立刻在C層開始做事情,因為這裡沒有業務,有的只是驗證客戶端傳過來的數據,以及對server層的調用返回。通過這個過程可以加速其融入團隊的進程。

統一的返回格式

約定api返回的數據格式,這基本上是系統開發開始的第一步,原先常用的方式就是在每個控制器中通過

returnjson_encode([ msg => ok ,// 攜帶的信息,可以用來前端 alert 提示用戶"data => [// 具體數據... ... ], code => 0 ,// 0表示成功,其他表示對應錯誤])

那麼這裡首先遇到的第一個問題,為了簡化前端對類型的判斷,基本上所有的欄位值,都是返回字元串形式。那麼 data 裡邊的內容就需要在每個控制器中進行處理字元串、utf-8編碼等問題。要重複代碼,就算你抽離成一個方法,也需要面對該問題。好點的解決方案是在返回數據的攔截器(每一個框架都有類似的概念)內進行統一的處理。

像上面這樣的代碼寫法,帶來的額外問題可能有,欄位名稱打錯,比如: code 寫成 cdoe ,data 寫成 date。為程序代碼額外的風險(尤其是bug修復時最容易出現該情況)

那麼一種解決辦法就該由此想到,採用對象的方式來規範化返回的數據結構。比如我們定義一個類:

classResultData{/** * 返回的信息提示 *@varstring $msg */private$msg;/** * 返回的數據結構 *@vararray|object|string */private$data;/** * api 狀態碼 *@varint $apiCode *@seeApiCode */private$apiCode;publicfunction__construct(int $apiCode, string $msg = ok , $data = null){$this->apiCode = strval($apiCode);$this->msg = trim(strval($msg));$this->data = $data; }/** * 獲取數據結果 *@returnarray */publicfunctiongetRetData(){if(! is_array($this->data) && is_object($this->data) && method_exists($this->data, toArray )) {$this->data =$this->data->toArray(); }// valueToString 將data的value轉化為 string 並且做utf-8轉碼$result = [ code =>$this->apiCode, msg =>$this->msg, data =>$this->data ? ArrayUtil::valueToString($this->data) : [], ];if(! APP_ENV_PROD) {// 測試環境顯示 api 的處理時間信息 方便優化$result[ use_time ] = microtime(true) - $_SERVER[ REQUEST_TIME_FLOAT ]; }return$result; }}

有了上面這個類,我們所有的服務層或者controller都應該用它作為返回值。然後在攔截器中統一進行json encode即可。這樣子即減少了犯錯的可能性,同時對統一處理數據的地方做了統一管理集中到 ResultData 中,那麼以後有什麼特殊變動,調整一處,處處生效。

其它問題

另外還有關於 oauth2 如何集成到項目中等等問題,這部分均放到 x-api 項目中進行說明,紙上說來終覺淺嘛。

日誌的記錄也是系統開發非常重要的部分,這部分沒什麼太多說的,用規範的格式,存儲指定的數據(介質可以是:db、file)。

系統開發中應該拒絕使用 、 這些方式進行調試,另外建議採用:PhpStorm IDE來進行系統開發。

點擊展開全文

喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 PHP技術大全 的精彩文章:

關於PHP協程與阻塞的思考
高並發下的下單功能設計
Uber醜聞不斷,被曝將問題車租給司機
VIM使用技巧及快捷操作
MySQL性能優化的最佳20 條經驗

TAG:PHP技術大全 |

您可能感興趣

DARPA CONTEXT項目尋求通過演算法模型確定戰爭的真實起因
項目評級——PTC
DARPA局長在國防會議上概述該機構的未來重點項目
BMW EDI項目成功案例
PHP7 JIT 相關開源項目
ONE.TOP 創始人教你如何快速識別區塊鏈項目?
EPIPHANY-基於NEO生態體系的重磅項目!
涉嫌壟斷方式打壓AMD:NVIDIA GPP項目遭FTC/歐盟調查
IPFS,分散式存儲項目
一步步編寫自己的PHP爬取代理IP項目
閱讀SSH項目之ERP
ICO項目評估
如何打造一個成熟的開源項目團隊?PingCAP聯合創始人黃東旭專訪紀要
IMAX 要把整個 VR 體驗店項目都關了,但這未必是壞事
微軟為OCP計算項目推出雲SSD存儲新規範
DARPA接近完成「拒止環境協同作戰」項目
區塊鏈項目不在公開ICO銷售ICO將重回IPO
涉嫌壟斷,NVIDIA項目遭FTC/歐盟調查
聊聊API對接,項目啟動前該調研點啥?
DARPA OFFSET項目的最新進展