寫在前面
這周開始學習ThinkPHP,將學習的日記記錄下來。不僅僅學習怎麼用TP,也要從源碼上來學習TP架構。
日記每天都寫,但不一定都放到網上。希望自己能夠堅持下去。
閑話少說,既然是閱讀源碼,關於TP的建立,配置等一系列操作就不去說了,官方文檔有佷詳細的介紹。
要同學想要學習TP的可以點擊 ThinkPHP3.2.3快速入門 學習,大家一起進步。
CURD操作
什麼是CURD操作?實際上是對資料庫增刪改查的簡稱。包括了create、update、read、delete四個基本操作。在TP中對CURD操作的實現是add,save,select,update。
開啟Think/Library/Model.class.php,可以在其中找到這四個操作。接下來就開始來查看源碼,知道啟動並執行流程,才能夠更好的運用這四個操作。
CUED操作之add方法
add方法用於資料添加,是TP對create操作的實現。注意一點的是,TPModel中也有create方法,但並不是CURD操作的一種,而是對即將插入資料庫的資料的處理方法。
參數分析
add方法有三個參數(不必須傳遞),如下
$data 預設值'' 需要進行插入資料庫的資料$option 預設值array() 運算式參數 其中儲存著 所有進行過的連貫操作$replace 預設值false 是否在插入資料庫時進行replace操作
傳回值可能是bool(false)或資料庫受影響的行數或主索引值。從傳回值看出該操作是必須位於連貫操作的末尾,可以看成一連套組合技中的終結技。
流程分析
我對add方法的執行流程分成了四步
- 首先,檢測資料是否為空白
- 其次,進行資料處理與運算式分析
- 以上都通過 進行資料插入 返回插入結果
- 對返回的結果進行分析
步驟一假設進行使用者註冊操作,插入資料表User,使用add方法進行操作。user欄位為:
主鍵 user_id暱稱 user_name密碼 password郵箱 email
前台POST資料:
array( 'user_name' => 'xiamsahfw', 'password' => 'adhe99211' , 'confrim' => 'adhe99211' , 'email' => '221131@qq.com', 'hid' => 'register' );
在UserController類中的操作:
$data = I('post.');$User = M('User');$User->create($data);$User->add();
在add操作中,並沒有給add傳遞任何參數,但在$User->create($data)中傳遞了該值,在該操作中就會自動將資料添加到Model中的$this->data中,而add會自動引用該值。
同時create方法會將自動將傳遞的參數與資料表的欄位進行對比,將不屬於表中的欄位刪除。
步驟二之後,add方法就會調用_facade方法對$data進行資料處理,其實在這裡是二次處理$data資料,因為在create方法以及對資料進行過處理。如果在UserController中並沒有調用create方法,而是直接傳遞$data到add方法,那麼_facade就會把'confrim' => 'adhe99211' ,'hid' => 'register'刪除,變成:
array( 'user_name' => 'xiamsahfw', 'password' => 'adhe99211' , 'email' => '221131@qq.com' );
為了可能的連貫操作,add會調用_parseOptions進行運算式分析。在運算式分析後即使沒進行任何連貫操作,在返回的值也存在兩個元素:
Array ([table] => user[model] => User)
table表示操作的資料表,model表示操作的模型名。
如果之前存在連貫操作,如where,group by等也會在該項顯示。此外,傳遞連貫操作到add方法,也會和已經存在的操作進行合并。
步驟三以上其實都是資料插入的準備工作,準備工作完成就能夠進行資料插入了。當然資料插入不屬於Model的功能,在TP中需要調用Think\Driver.class.php中的insert方法。
insert方法接受三個參數
$data$option$replace
前兩個參數是處理過的資料以及組合後的連貫動作表達式,第三個參數表示在插入資料庫時,是否進行replace操作,預設為false。在這個方法中會將傳遞的資料與連貫動作表達式進行組合,形成正式的sql語句,並執行sql語句。最後返回執行結果。
步驟四雖然得到了返回結果,add並不是直接將結果返回,而是返回分析後的結論。insert返回的結果,可能有:
失敗 => false成功 => 返回受影響的行數
但是實際進行中,我們可能會不僅想要得到一個插入成功的結論,而是想要得到插入後的主索引值。在add方法中會對返回結果進行判斷,從而返回受影響的行數(多條資料插入)或主索引值(一條資料)或false。
題外話:在進行資料插入之前我注意到有這麼一行代碼。
if(false === $this->_before_insert($data,$options)) { return false;}
這裡TP沒有做任何注釋,尋找之後,發現是一個空方法,解釋為 插入資料前的回調方法
// 插入資料前的回調方法protected function _before_insert(&$data,$options) {}
將這個方法列印出來,結果為NULL
var_dump($this->_before_insert($data,$options)); // NULL
百度一下也沒找到想要的答案,我對TP的官方文檔並沒有看完,可能官方會有用法的介紹。這裡很糾結,我猜測是在子類繼承時,可以實現這個方法進行某些特殊操作(很大可能)。與之相同的還有_after_insert方法。
總結
寫了一大串,也不知道寫的是不是很清晰,但是我的確是對這個方法熟悉了很多。這個方法雖然可以不傳遞參數,但如果之前沒進行create還是會出錯的,雖然內部整合了資料處理,但不是很完善,比如對資料沒能進行轉義,也不能夠對資料欄位進行驗證,需要我們自己進行調用其它方法等等。知道了add的運行原理,自然能夠很好的運用它,同時對自己封裝模型類時也有了很大啟發。
今天就寫到這兒,下一篇準備寫CURD中的read,也就是TP中的select。
博主大三狗,正在努力學習中,文中有錯漏之處難免,歡迎指正,歡迎批評。