這篇文章主要介紹ThinkPHP中如何定義修改器,文中介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們一定要看完!
定義修改器
修改器的作用是在模型對象數(shù)據(jù)寫入數(shù)據(jù)庫之前進行一些必要的數(shù)據(jù)處理,修改器的標準定義如下:
public function setFieldNameAttr($value, $data) { // 對value值進行處理 data參數(shù)是當(dāng)前全部數(shù)據(jù) // 返回值就是實際要寫入數(shù)據(jù)庫的值 return $value; }
其中FieldName對應(yīng)數(shù)據(jù)表的field_name字段(注意數(shù)據(jù)表字段的規(guī)范和修改器方法定義規(guī)范,否則會導(dǎo)致錯誤)。
原則上,每個修改器應(yīng)當(dāng)僅處理對應(yīng)字段的數(shù)據(jù),但在必要的情況下允許同時處理多個字段。
下面是一個例子
public function setBirthdayAttr($value, $data) { // 格式化生日數(shù)據(jù) $birthday = strtotime($value); // 根據(jù)生日判斷年齡 $age = getAgeByBirthday($birthday); // 賦值年齡數(shù)據(jù) $this->setAttr('age', $age); return $birthday; } public function setAgeAttr($value,$data) { return floor($value); }
之所以使用setAttr方法是確保年齡賦值操作仍然可以走單獨的修改器。如果你沒有額外的修改器,那么也可以寫成
public function setBirthdayAttr($value, $data) { // 格式化生日數(shù)據(jù) $birthday = strtotime($value); // 根據(jù)生日判斷年齡 $age = getAgeByBirthday($birthday); // 賦值年齡數(shù)據(jù) $this->data['age'] = $age; return $birthday; }
注意一定不能寫成
$this->age = $age;
因為在模型內(nèi)部進行數(shù)據(jù)對象的賦值,會因為和模型內(nèi)部屬性混淆而導(dǎo)致不可預(yù)知的后果。
如果你在某個修改器中可能會對其它字段進行修改,務(wù)必記得你需要額外修改的字段修改器必須已經(jīng)經(jīng)過賦值操作(或者已經(jīng)觸發(fā)過修改器)。
如何調(diào)用
修改器方法不需要手動調(diào)用,按照定義規(guī)范定義好后,系統(tǒng)會在下面的情況下自動調(diào)用:
·模型對象賦值;
·調(diào)用模型的data方法,并且第二個參數(shù)傳入true;
·調(diào)用模型的save方法,并且傳入數(shù)組數(shù)據(jù);
·顯式調(diào)用模型的setAttr方法;
·定義了該字段的自動完成;
例如User模型定義了setPasswordAttr修改器方法。
public function setPasswordAttr($value, $data) { return md5($value); }
當(dāng)下面這樣使用的時候,保存到數(shù)據(jù)庫的password字段的值就會變成md5('think')后的值。
$user = User::get(1); $user->password = 'think'; $user->save();
如果你在一些情況下,不希望使用修改器而是想要手動控制數(shù)據(jù),可以嘗試使用下面的方法。
$user = User::get(1); $user->data('password', md5('think')); $user->save();
這個時候就不會經(jīng)過修改器處理。
避免沖突
很多開發(fā)者喜歡給修改器定義自動完成auto(包括insert和update)。
protected $auto = ['password'];
這在V5.1.27版本之前是一個看似聰明卻非常致命的錯誤,要盡量避免,因為根據(jù)我們之前給出的修改器觸發(fā)條件,會導(dǎo)致該修改器被執(zhí)行兩次。這會是一個災(zāi)難性的錯誤,將導(dǎo)致所有的用戶注冊后都無法正常登錄。
解決辦法取消password字段的自動完成設(shè)置,因為修改器會在每次賦值的時候自動觸發(fā),如果沒有賦值說明密碼沒有被修改,也談不上自動完成。
自動完成的字段通常是不在表單里面的字段,一般是由系統(tǒng)自動處理的字段。
V5.1.27版本改進了這個問題,所有的修改器只允許執(zhí)行一次,上面的問題就不復(fù)存在了。但好像又帶來了一個新的問題,很多時候,你也許想在模型的事件中對數(shù)據(jù)進行修改。
User::beforeUpdate(function($user) { $user->password = md5('think'); });
會發(fā)現(xiàn),在模型beforeUpdate事件中,數(shù)據(jù)的值怎么都修改不了,原因是模型的修改器之前在第一次賦值的時候已經(jīng)執(zhí)行了,第二次再賦值的時候已經(jīng)無效了(不會再執(zhí)行)。
解決辦法就是我前面提過的使用data方法不調(diào)用修改器進行數(shù)據(jù)賦值操作。
User::beforeUpdate(function($user) { $user->data('password', md5('think')); });
當(dāng)然,更好的建議是規(guī)劃好修改器、自動完成和模型事件的數(shù)據(jù)處理機制,不要對一個字段同時使用多重機制修改數(shù)據(jù),并且寫入數(shù)據(jù)庫的數(shù)據(jù)應(yīng)該并且只有修改器這一個途徑進行數(shù)據(jù)修改操作。
類型自動轉(zhuǎn)化
如果你的修改器僅僅是對數(shù)據(jù)做類型轉(zhuǎn)換處理的話,可以無需定義修改器,而是直接定義字段類型就可以了。
public function setScoreAttr($value, $data) { return (float) $score; }
上面的修改器方法可以直接改成
protected $type = [ 'score' => 'float', ];
如果你同時對一個字段定義了修改器和類型的話,修改器是優(yōu)先的。
類型定義不僅能定義簡單的數(shù)據(jù)類型,還有一些額外的用途,例如:json 類型、array類型和object 類型會進行JSON序列化,serialize類型則會把數(shù)據(jù)進行serialize序列化。
以上是“ThinkPHP中如何定義修改器”這篇文章的所有內(nèi)容,感謝各位的閱讀!希望分享的內(nèi)容對大家有幫助,更多相關(guān)知識,歡迎關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道!
分享標題:ThinkPHP中如何定義修改器-創(chuàng)新互聯(lián)
本文URL:http://jinyejixie.com/article22/djhicc.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供手機網(wǎng)站建設(shè)、外貿(mào)建站、自適應(yīng)網(wǎng)站、小程序開發(fā)、用戶體驗、網(wǎng)站維護
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)