計算機軟件技術發展至今,數據庫已成為最廣泛使用的存儲格式化數據的媒介,數據庫程序開發技術也日趨完善,大型的ORM框架使得數據庫程序開發變得簡單,並已成為操作關系型數據庫的主流方式。數據庫程序主要代碼為CRUD(create, retrieve, update, delete)代碼,隨著ORM框架功能的完善,編寫CRUD代碼也衍生其固定的流程,對不同數據庫表進行操作的CRUD代碼也存在高度可重用性。當前編寫重復性的CRUD代碼成為開發人員的常態,不僅嚴重降低其積極性,而且損失其開發效率,所以迫切需要一種能夠快速生成CRUD代碼的產品,以期減少這方面的工作,提高開發效率。
目前國外已經誕生一些解決上述需求的、具有很高可用性的CRUD生成器產品:CrudKit,CRUD-Admin-Generator,Dadabik,GroceryCrud,SximoBuilder。這些產品各有其特點,但也有一共同點:都是基於PHP進行開發(這在一定程度上決定於PHP語法的靈活性及其解析性)。SximoBuilder是其中的典型代表,盡管SximoBuilder設計獨特、可用性高、流行度高,但也存在如下不足之處:
然而對於當今日益復雜的web程序,上述幾點是開發過程必須考慮的問題,因此,開發一款既具有SximoBuilder現有功能、又完善其不足之處的CRUD生成器產品,勢在必行。
基於國內外CRUD生成器研究現狀,筆者開發一款名為DBuilder(D為DataAdministrator的簡寫)的CRUD 生成器。
DBuilder借鑒SximoBuilder的模塊為代碼單元、由模板生成代碼的思想,但擁有與SximoBuilder完全不同的代碼生成器邏輯。它在實現SximoBuilder核心的代碼生成、通用CRUD兩種功能的基礎上,通過重寫代碼邏輯完善其不足之處:代碼冗余度大、缺少前端驗證。
DBuilder面向的主要用戶人群為web後台管理員以及開發人員,因此其系統分析過程,將更多的站在web後台管理員及開發人員的角度考慮問題。
項目需要實現如下幾點核心功能。
1) 數據源管理
用戶可以在界面為項目配置多個數據源。配置的數據源信息包括數據庫類型、地址、數據庫名、端口、用戶名、密碼等信息。支持對數據源的增刪改查,保證對數據源的增刪改查不輕易造成系統問題。
2) 代碼生成
此功能是DBuilder的核心要實現的功能,用戶在選擇數據源和數據表之後,能夠對數據庫表的字段做簡單配置,配置包括Form表單配置、List(Table)列表配置、關系配置、全局屬性配置。配置完成後DBuilder要能生成對數據庫表的CRUD的MVC代碼,即需要實現CRUD可用功能,但不用編寫代碼。
3) 數據庫表CRUD
生成的代碼必須支持數據表記錄的新建、刪除、更新、查詢操作。
4) 菜單管理
DBuilder要能將生成的代碼跟一個菜單項綁定,讓用戶點擊菜單項之後,就可以使用DBuilder生成的CRUD功能。此菜單必須包括後台菜單,前台菜單不是必須的。
5) 用戶管理
用戶要實現多種角色。必須能夠以郵箱為用戶唯一標識,並作為登錄參數。未來還要實現支持QQ、微信、新浪微博基於OAuth2.0的互聯登錄。
6) 權限管理
DBuilder要能實現不同用戶角色對不同CRUD代碼的執行、訪問權限做到三維的可配置。譬如,現有一個文章管理的CRUD功能模塊,用戶角色分為系統管理員(SuperAdmin),管理員(Admin),訪客(Guest),那麼DBuilder要能實現如下的三維權限配置,且將之作為所有Module的默認權限。
表2-1 Module權限配置表
用戶組與權限
查看
編輯
刪除
導出
SuperAdmin
√
√
√
√
Admin
√
√
√
Guest
√
7) 站點參數配置
DBuilder作為一個網站的web後台程序,對站點的全局參數配置也是必須的,這些參數包括網站名字、關鍵詞、聯系地址、友情鏈接等等。
8) 操作日志
DBuilder要記錄用戶的操作信息,包括訪問的頁面、執行的CRUD類型、時間等等信息。日志的記錄形式支持數據庫和文件兩種方式。
9) 多語言支持
DBuilder要支持多國語言的切換。至少應該支持中文和英語兩種語言,且以中文為默認。
10) 多數據庫類型支持
DBuilder要支持多種類型數據庫,暫時主要支持關系型數據庫,包括mysql,MS SqlServer,oracle,PostGreSQL等等。
按照需求提取可得實體有:用戶、用戶組、數據源、代碼模塊、菜單,關系有:權限、日志。實體與關系的含義如下:
實體與關系的ER圖如下:
圖2-1 ER圖
DBuilder應該要做成一套高性能、高可用的CRUD生成器,為此DBuilder設計中應該符合下面幾項原則:
DBuilder有下面2個核心的構件Core CRUD 模塊和GModule,GModule對Core CRUD 模塊有繼承依賴的關系,GModule由MVC Code和CRUD Config組成;Core CRUD模塊是手工編寫的代碼,而GModule是DBuilder生成的代碼;Core CRUD 模塊實現CRUD操作,GModule實現擴展功能。下圖表示了這兩個構件的組成和關系
圖3-1概念與構件
下面對圖中設計的概念、構件、模塊關系以及Build與CRUD流程做詳細闡述。
Core CRUD 模塊實現核心CRUD操作,一切對GModule MVC中Controller的CRUD請求,最終轉交至Core CRUD 模塊進行處理。Core CRUD 模塊會開放一些預處理和後處理接口交由GModule實現,這些接口會在Model,Controller,View上都有體現。
Core CRUD 模塊主要包括如下文件
Core CRUD 模塊讀取GModule Configuration實現真正的CRUD操作。
GModule(Generated Module)不但實現了Core CRUD Module接口(MVC代碼),而且具有自己配置文件(CRUD Configuration)。每一GModule表示以一張數據庫表為主表,具備CRUD功能的代碼文件合集(包括對應的MVC + Configuration代碼)。譬如,DBuilder生成的一個GModule, 主表為core數據源user表,名字為User,那麼User GModule應包含下面代碼文件:
代碼文件命名取決於GModule的名字,故為保證生成的代碼文件不沖突,取GModule的名字(GModule Key,GModule Name)作為GModule的唯一標識。每一個GModule的信息都被保存在數據庫中。一次新建 GModule操作將會新建上述所有代碼文件,更新相關文件,並插入一條GModule記錄到數據庫。一次更新 GModule操作將只會更新Configuration文件。
GModule 由MVC代碼和CRUD Configuration代碼組成,下面分別進行闡述:
GModule並不表示具體某一個模塊,而是代指一類模塊,這種模塊可以由DBuilder生成,或者由開發人員手工建立。它主要用來實現Core CRUD Module的接口,主要包括下述幾部分
1) Controller接口
假設GModule模塊的 Controller為A,Core CRUD Module 的Controller為B,則A應繼承自B。CRUD請求會先路由到A,而實際的處理者是B。A會實現B開放的下列接口。
2) Model 接口
GModule MVC代碼中的Model也繼承自BaseModel,實現 BaseModel類開放的一些接口可以完成擴展。
formatXXXAttribute():該接口用來格式化某個字段。本產品基於Laravel,其已經具備類似的接口,就是getXXXXAttribute()。但這樣的接口的優先級比字段優先級高,這在特殊的情況下為開發帶來了不便,所以再設計一個類似的接口,該接口的優先級低於字段本身。
3) View 接口
視圖的擴展接口與前兩者不同,主要體現在子視圖與視圖塊上,也就是在Core CURD模塊的視圖基礎上,擴展視圖組件。默認Core CRUD MVC視圖生成的是一個表格或者一個表單,占滿頁面。而View接口將提供在該表格上下左右擴展頁面組件的能力。
4) Configuration
每一個GModule對應一個Configuration文件,其中包含GModule對主表各個字段的配置參數,以及布局參數。
CRUD請求路由到GModule的Controller,GModule代碼實現Core CRUD MVC開放的接口,而由Core CRUD Module去真正實現對數據庫的CRUD操作。每一個GModule的信息應該被記錄在數據庫表中,以便給GModule關聯菜單,控制權限,記錄操作日志等等。一些主要模塊之間的關系如下圖所示。
圖3-2模塊關系
從圖2-2中可以看到,由GModule管理模塊根據用戶配置來生成一個GModule A,當用戶的CRUD請求到達GModule A時,GModule 會講請求轉交Core CRUD進行處理,Core CRUD 模塊再以SQL對數據庫進行CRUD操作。
DBuilder項目的方案,將真正的CRUD操作交給了Core CRUD Module去執行,CRUD參數由GET或者POST請求參數與GModule Configuration構成,而GModule的MVC代碼只是去實現Core CRUD MVC開放的一些預處理或者後處理接口。
圖2-3是DBuilder最核心的流程圖,包含Module的生成和處理CRUD請求的過程,圖2-4是SximoBuilder 中Module的生成和處理CRUD請求的流程圖。
圖3-3 DBuilder 代碼生成和處理CRUD的流程
圖3-4 SximoBuilder 代碼生成和處理CRUD的流程
對比兩者,可以看到兩者的最大區別,是DBuilder復用一份CRUD代碼,而不是像Sximo那樣為每一個Module生成一套可以當獨執行的CRUD代碼。這樣做的好處是提高了復用性,並通過Module CRUD MVC實現預處理/後處理接口達到擴展性的目的。
Core數據源是DBuilder的默認數據源,其類型為mysql,數據庫名為dbuilder,本節按照《數據原型分析》一節進行詳細的數據庫設計。為提高程序性能,數據源信息保存在代碼文件app/config/datasource.php中,文件內容如下:
<?php return array (
'core' =>
array (
'driver' => 'mysql',
'host' => 'localhost',
'database' => 'dbuilder',
'username' => 'root',
'password' => 'root',
'charset' => 'utf8',
'collation' => 'utf8_unicode_ci',
'prefix' => '',
'edit' => false,
'port' => 3306,
),
// more data source
);
其中Core數據源有下述數據表:
1) d_menu 表:表示後台左側樹形菜單,每一個可點擊跳轉的菜單項必須與一個Module進行關聯。
表3-1 web後台左側菜單表