1. 程式人生 > >ThinkPHP中的getLastSql函式---獲取上次執行的SQL語句

ThinkPHP中的getLastSql函式---獲取上次執行的SQL語句

Thinkphp是我們經常用使用的一個php的MVC框架。通常我們把業務分類,分層,在不同的層處理不同的業務邏輯。

本文要講的是model層,關於獲取上次執行的SQL語句的問題。(用於日誌記錄,或者分析出錯原因等)。

1:model層的一般情況

通常,我們是通過整合系統Model類的方式來實現的。比如:class UserModel extends Model;(此文不多考慮名稱空間的問題,即忽略3.1和3.2的差別)

更有甚至,有一個model的基類。class BaseModel extends Model,然後:class UserModel extends BaseModel,

當然,也有些初學者,或者業務邏輯簡單的情況,直接在C層,M一個系統model類,然後處理業務邏輯。

本文不討論沒有M層的情況。

2:getLastSql函式

看過Thinkphp中Model類的人,都能發現這個函式,甚至還有,getLastInsID,getDbError,getError,getPk,getDbFields等函式。這些函式都是我們經常可能會用到的model層的函式。這裡只說getLastSql函式。

此函式返回上次執行的SQL語句。

但是這句話不是太好理解的。

如果,我們使用,debug_backtrace,生成一條回溯跟蹤線。經常會發現:

[Sweep] => SHOW COLUMNS FROM `sweep_info`
[sweep_info] => SELECT * FROM `sweep_info` WHERE `sweep_result` = '' AND `status` = 0 
有兩條SQL語句。很顯然,第一條不是我們需要的。(實際上,第一條是獲取資料庫表中的欄位名,用於欄位的驗證,這是TP的可配置功能)
那麼,如何獲取第二條SQL語句?
3:多個model類的繼承關係:
上面的問題,需要考慮到之前我們提到的常見model情況。情況裡,存在了兩級甚至三級的繼承關係。(實際上,這個繼承關係也只是第一條SQL語句需要考慮的)。
那麼,現在我們先來弄清楚一個問題。這兩條SQL語句都是誰執行的?
這個問題其實很簡單:我們程式碼裡的哪些函式可能會執行SQL語句?那麼,這些方法在哪個類裡宣告的?很顯然,是Think的model類。也就是繼承關係最上面的那個類。
那麼,這兩個SQL語句都是系統的model類執行的?
是的。準確點兒說,是這個類的兩個物件一人執行了一條。(這個說法不太準確,準確的說,是每個物件裡的DB物件,DB是個單例,都是這個單例執行的。只不過,我們在獲取這兩條SQL的時候,是用model物件獲取,而非DB物件,所以,簡單的理解成“兩個物件一人執行了一條”)
4:獲取第二條SQL語句
上面我們說了很多,其實都是一個理解的過程。真實的操作很簡單。如下:
class UserModel extends Model(BaseModel){
public function test($data){
$model = M('user');
$model->add($data);
$sql = $model->getLastSql();
}
}
這裡的$sql就是我們需要的第二條。是吧,真實的實現,其實是很簡單的。
5:思考:為什麼會這樣?
問題即是:為什麼是兩個model物件,為什麼是兩條SQL語句?為什麼這樣就可以得到我們剛才執行的SQL語句?(上面的例子程式碼,其SQL應該形如:Insert into user(...) values(...))
答案:
UserModel在例項化的時候,其實就是model的一個例項化過程。第一條SQL語句,可以理解成UserModel在例項化的時候執行的,獲取了一下表中的欄位資訊(這種說法不太準確,想要了解,還是去看原始碼)。這是第一個物件,也是第一條SQL語句。
而在test函式裡,我們例項化了一個Model,($model = M('user');其實,D和M方法,就是一個例項化的過程)這是第二個物件,對應的:$model->add($data);當然就是執行第二條SQL語句的地方。(這個往往也是我們想要檢視的SQL語句)。
再多說一點,其實getLastInsID,getDbError,getError,getPk,getDbFields這些函式的實現過程,在理解上,也就是上面的關係和情況。理解清楚是“這兩個物件裡的哪個物件”,可以避免:$this-> 呼叫還是 $model->呼叫的問題。