我把模型分成了幾塊兒,A,B,C,D,E,F,這幾塊兒分別代表了什麼呢?
首先A,這個Base代表的就是整個架構的基類,所有的模型檔案都必須繼承自這個基類;
由於B的內容需要依賴D,所以先說一下D,D首先有一個ConnectionManager,它負責管理資料庫的串連和關閉還有資料庫驅動的選擇,這個命名自己感覺不太好,先就將就吧,既然它負責資料庫的串連和關閉,肯定它就有以下方法:
2 |
public class ConnectionManager { |
3 |
public static function getConnection(){} |
4 |
public static function releaseConnection() {} |
由於資料庫的串連對於所有模型來說都是共用的,所以我們把ConnnectionManager設定為單例。
D中右邊有PDO,MYSQL_*,這代表什麼意思呢,實際上就是代表各種驅動,有可能你使用的是比較先進的PDO,也有可能你使用的是比較老的MYSQL_*這種,也有可能你使用的是mysqli,ADO等等,正是由於PHP資料庫這一塊兒的混亂情況,我們需要在架構中定義一個契約,所有的驅動類按照這個契約編寫實現,這樣,不管驅動類的底層實現怎樣,但是上層看到的內容都是一致的。
現在我們定義一下這個契約:
03 |
function execute($sql); |
06 |
function getAllByObject(); |
07 |
function getAllByAssocArray(); |
08 |
function getAllByArray(); |
09 |
function beginTrans(); |
connect就是串連資料庫,execute就是執行一個SQL,如果這個SQL是一個查詢,那麼getAllByObject代表將查詢的結果通過對象返回,getAllByAssocArray代表將結果按照關聯陣列返回,getAllByArray代表將結果按照普通數組返回,beginTrans代表開啟一個事務,即開啟autoCommit,commit就是提交事務,rollback是將交易回復,close就是關閉Db。
其實,在將查詢的結果返回的時候,還可以封裝成為一個iterator。
好,我們現在再來看看B,首先看看ModelBase,它實際上是提供給表模型和關聯式模式使用的,它封裝了外部可見的各種函數,如query,insert,update,delete,execute,fetchAll等等,那也就是說B中所有的驅動類外部都是不可以直接存取的,那麼誰訪問呢,就是ModelBase,但是它又不直接存取,而是通過ConnectionManager來訪問。
由於ConnectionManager會按照設定檔自動選擇驅動,所以ModelBase也不知道到底它調用的是哪一個驅動類,但是由於驅動類都遵循契約,所以ModelBase不用管到底是那個驅動,就可調用契約上面的方法了。
02 |
class ModelBase extends Base { |
03 |
protected $_db = null; |
04 |
public function __construct() { |
05 |
$this->_db = ConnectionManager::getConnection(); |
07 |
public function execute($sql) { |
08 |
$this->_db->execute($sql); |
就比如上面這段代碼,首先在執行個體化ModelBase的時候,就會調用ConnectionManager的getConnection擷取資料庫的串連,當然,由於ConnectionManager是單例的,所以即使同時執行個體化了10個ModelBase類,資料庫的串連操作也只有一次。
由於有了上面的契約,在這一層執行一個SQL非常簡單,只要調用驅動類的execute方法即可,即$this->_db->execute($sql);
說了ModelBase,再說一下SQL Parse,它主要的功能就是完成SQL的解析,什麼時候需要SQL的解析呢,實現資料庫的ORM的時候。
這一層也是由ModelBase調用的,假設現在外部有一個查詢操作,調用的方式是$this->where()->order()->select(),當然,每個函數的參數我都沒寫,這種函數鏈非常友好,SQL Parse就會去解析這幾個函數的實際意義,然後返回給ModelBase,ModelBase拿到解析之後的SQL,然後執行$this->_db->execute($sql)即可,所以不管花樣是那樣,最終都還是調用了驅動類的execute方法執行一條SQL的。
下面的C實際上就容易理解了,就是表模型和關聯式模式,由於一些操作在ModelBase中已經做完了,所以只要表模型和關聯式模式繼承ModelBase即可。表模型由於處理的是單表的內容,所以它有額外的內容,比如在執行一個$this->select()的時候 ,我們沒有指定查詢的內容,系統應該能夠識別它要查詢的表是什麼,可能最終解析的SQL就是:select * from XXX了,關聯式模式也是一樣。
說完了C,E也很容易理解,模型這一層實際上就是調用關聯式模式或者表模型的方法實現具體的業務即可。
F中是處理和普通資料庫以外的其他內容,比如Cache,由於這裡只是講一下思路,所以這塊兒的內容暫時不寫,如果有時間就後面再講,如果沒有,那就算了。