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